• 自動秒收錄
  • 軟件:1972
  • 資訊:55245|
  • 收錄網站:118546|

IT精英團

JavaScript私有屬性的各種實現的集合

JavaScript私有屬性的各種實現的集合

瀏覽次數:
評論次數:
編輯: 樂詠
信息來源: ITPUB
更新日期: 2022-04-01 18:32:09
摘要

來源|http://www.fly63.comJavaScript被很多人認為并不是一種面向對象語言,原因有很多種,比如JavaScript沒有類,不能提供傳統的類式繼承;再比如JavaScrip

  • 正文開始
  • 相關閱讀
  • 推薦作品

來源| http://www.fly63.com

很多人認為JavaScript不是面向對象的語言,原因有很多。比如JavaScript沒有類,不能提供傳統的類繼承。比如JavaScript不能隱藏信息,不能實現私有成員。

本文無意打破以上誤區(其實作者自己也很困惑),只是簡單介紹一下JavaScript中私有屬性的幾種實現方式,以及各自的優缺點。

00-1010很多編碼規范規定以下劃線_開頭的變量是私有成員,便于與團隊開發人員協作。實現如下:

功能人(姓名){ this。_ name=name}var person=新人(' Joe ');這種方式只是一種規范性的約定,很容易被打破。而且,私有財產也沒有落實。上面代碼中的實例person可以直接訪問_name屬性:

警戒(人。_ name);//'Joe'

1、基于編碼規范約定實現方式

另一種常見的方式是利用JavaScript的閉包特性。局部變量和特權函數是在構造函數中定義的,它們的實例只能通過特權函數訪問這個變量,如下所示:

函數Person(name){ var _ name=name;this . getname=function(){ return _ name;}}var person=新人(' Joe ');這種方法的優點是私有屬性是隱藏的,Person的實例不能直接訪問_name屬性,只能通過特權函數getName得到:

警戒(人。_ name);//undefinedalert(person . getname());//'Joe '使用閉包和特權函數來定義和訪問私有屬性,這是很多開發者采用的方式。但是這種方法有一些缺點:

私有變量和特權函數只能在構造函數中創建。一般來說,構造函數的功能只負責創建新的對象,方法要在prototype上共享。功能本質上存在于每個實例中,而不在原型上,增加了資源占用。

2、基于閉包的實現方式

JavaScript不支持地圖數據結構。所謂的強引用哈希表,其實就是Map pattern的變種。簡單來說就是給每個實例添加一個唯一的標識符,以這個標識符為鍵,對應的值就是這個實例的私有屬性。這對鍵值存儲在一個對象中。實現如下:

var Person=(function(){ var privateData={ },privateId=;函數Person(name){ object . define property(this,' _id ',{ value : private id });

>
privateData[this._id] = {name: name};}
Person.prototype.getName = function() {return privateData[this._id].name;};
return Person;}());

上述代碼的有以下幾個特征:

  1. 使用自執行函數創建Person類,變量privateData和privateId被所有實例共享;

  2. privateData用來儲存每個實例的私有屬性name的key-value,privateId用來分配每個實例的唯一標識符_id;

  3. 方法getName存在于prototype上,被所有實例共享。

這種方式在目前ES5環境下,基本是最佳方案了。但是仍然有一個致命的缺陷:散列表privateData對每個實例都是強引用,導致實例不能被垃圾回收處理。如果存在大量實例必然會導致memory leak。

造成以上問題的本質是JavaScript的閉包引用,以及只能使用字符串類型最為散列表的key值。針對這兩個問題,ES6新增的WeakMap可以良好的解決。

4、基于WeakMap的實現方式

WeakMap有以下特點:

1)、支持使用對象類型作為key值;

2)、弱引用。

根據WeakMap的特點,便不必為每個實例都創建一個唯一標識符,因為實例本身便可以作為WeakMap的key。改進后的代碼如下:

var Person = (function() {
var privateData = new WeakMap();
function Person(name) {privateData.set(this, { name: name });}
Person.prototype.getName = function() {return privateData.get(this).name;};
return Person;}());

改進的代碼不僅僅干凈了很多,而且WeakMap是一種弱引用散列表, 這意味著,如果沒有其他引用和該鍵引用同一個對象,這個對象將會被當作垃圾回收掉。解決了內存泄露的問題。

不幸的是,目前瀏覽器對WeakMap的支持率并不理想,投入生產環境仍然需要等待。

5、基于Proxy約束

Proxy 可以定義目標對象的 get、set、Object.keys 的邏輯,可以在這一層做一下判斷,如果是下劃線 _ 開頭就不讓訪問,否則就可以訪問。

比如還是這個 class:

class Dong {constructor() {this._name = 'dong';this._age = 20;this.friend = 'guang';}hello() {return 'I\'m ' + this._name + ', '  + this._age + ' years old';}}const dong = new Dong();

我們不直接調用它的對象的屬性方法了,而是先用一層 Proxy 來約束下 get、set、getKeys 的行為:

const dong = new Dong();const handler = {get(target, prop) {if (prop.startsWith('_')) {return;}return target[prop];},set(target, prop, value) {if (prop.startsWith('_')) {return;}target[prop] = value;},ownKeys(target, prop) {return Object.keys(target).filter(key => !key.startsWith('_'))},}const proxy = new Proxy(dong, handler)

我們通過 new Proxy 來給 dong 定義了 get、set、ownKeys 的 handler:

  • get: 如果以下劃線 _ 開頭就返回空,否則返回目標對象的屬性值 target[prop]。

  • set: 如果以下劃線 _ 開頭就直接返回,否則設置目標對象的屬性值。

  • ownKeys: 訪問 keys 時,過濾掉目標對象中下劃線開頭的屬性再返回。

這樣就實現了下劃線開頭的屬性的私有化:

我們測試下:

const proxy = new Proxy(dong, handler)
for (const key of Object.keys(proxy)) {console.log(key, proxy[key])}

確實,這里只打印了共有屬性的方法,而下劃線開頭的那兩個屬性沒有打印。我們基于 _prop 這種命名規范實現了真正的私有屬性!

6、Symbol用于創建唯一的值

Symbol 是 es2015 添加的一個 api,用于創建唯一的值?;谶@個唯一的特性,我們就可以實現私有屬性。

比如這樣:

const nameSymbol = Symbol('name');const ageSymbol = Symbol('age');class Dong {constructor() {this[nameSymbol] = 'dong';this[ageSymbol] = 20;}hello() {return 'I\'m ' + this[nameSymbol] + ', '  + this[ageSymbol] + ' years old';}}const dong = new Dong();

我們不再用 name 和 age 作為私有屬性名了,而是用 Symbol 生成唯一的值來作為名字。

7、es新草案 #prop

現在有一個私有屬性的 es 草案,可以通過 # 的方式來標識私有屬性和方法。

比如這樣:

class Dong {constructor() {this.#name = 'dong';this.#age = 20;this.friend = 'guang';}hello() {return 'I\'m ' + this.#name + this.#age + 'years old';}}

這里的 name 和 age 都是私有的,而 friend 是共有的。

這種新語法 JS 引擎沒那么快支持,但是可以通過 babel 或者 ts 編譯器來編譯成低版本語法的方式來提前用。

比如 babel 有 @babel/proposal-private-property-in-object 的插件,它可以實現這種語法的編譯。


標簽:屬性 實例 方式
一張圖介紹JS原型鏈的來龍去脈
? 上一篇 2022-04-01
  • 一張圖介紹JS原型鏈的來龍去脈
    0閱讀 0條評論 個贊
    前言在面向對象編程中,繼承是非常實用也非常核心的功能,這一切都基于面向類語言中的類。然而,javascript和面向類的語言不同,它沒有類作為藍圖,javascript中只有對象,但抽象繼承思想又是如……
  • 還記得神奇的SQL查詢體驗嗎 按慢速查詢優化分組
    0閱讀 0條評論 個贊
    一、問題背景現網出現慢查詢,在500萬數量級的情況下,單表查詢速度在30多秒,需要對sql進行優化,sql如下:我在測試環境構造了500萬條數據,模擬了這個慢查詢。簡單來說,就是查詢一定條件下,都有哪……
  • 談Java并發下的樂觀鎖
    1閱讀 0條評論 個贊
    引子各位少俠大家好!今天我們來聊聊Java并發下的樂觀鎖。在聊樂觀鎖之前,先給大家復習一個概念:原子操作:什么是原子操作呢?我們知道,原子(atom)指化學反應不可再分的基本微粒。在Java多……
  • 2022年前端技術發展趨勢綜述
    3閱讀 0條評論 個贊
    “天下大勢,浩浩湯湯,順之者昌,逆之者亡?!币韵率菍η岸烁魑淮罄?021總結的一個匯總總結。希望可以看到一些前端行業的動向,排布。幫助團隊和自身制定未來的規劃。內容分為四個部分:基礎框架/工程化語言行……
  • MySQL用限制為什么會影響性能?
    0閱讀 0條評論 個贊
    一.前言首先說明一下MySQL的版本:mysql>selectversion();+-----------+|version()|+-----------+|5.7.17|+----……
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
  • JavaScript私有屬性的各種實現的集合
    0閱讀 0條評論 個贊
    來源|http://www.fly63.comJavaScript被很多人認為并不是一種面向對象語言,原因有很多種,比如JavaScript沒有類,不能提供傳統的類式繼承;再比如JavaScrip……
  • Mysql數據庫查詢這么慢 除了索引 還能是什么?
    1閱讀 0條評論 個贊
    作者|小白出品|小白debug(ID:xiaobaidebug我熟練應用ctrlc和ctrlv開發curd代碼好多年了。mysql查詢為什么會慢,關于這個問題,在實際開發經常會遇到,而面試中……
  • 10分鐘了解微服務、容器和Kubernetes
    2閱讀 0條評論 個贊
    什么是微服務?什么是微服務?你應該使用微服務嗎?微服務與容器和Kubernetes有什么關系?如果這些事情在您的日常生活中不斷出現,并且您需要在10分鐘內進行概述,那么這篇博文適合您。從根本上……
  • Shell analysis server log命令的這些亮點非常棒!
    1閱讀 0條評論 個贊
    自己的小網站跑在阿里云的ECS上面,偶爾也去分析分析自己網站服務器日志,看看網站的訪問量??纯从袥]有黑闊搞破壞!于是收集,整理一些服務器日志分析命令,大家可以試試!1、查看有多少個IP訪問:aw……
  • openGauss數據庫在可計算存儲CSD上的探索
    2閱讀 0條評論 個贊
    點擊藍字關注我們最近在可計算存儲CSD2000上使用BenchmarkSQL和sysbench測試了一下openGauss數據庫,主要觀察在大數據量下openGauss在CSD……
  • Linux——11步驟教你檢查服務器是否被完美入侵
    1閱讀 0條評論 個贊
    原文連接:https://zhuanlan.zhihu.com/p/441837141隨著開源產品的越來越盛行,作為一個Linux運維工程師,能夠清晰地鑒別異常機器是否已經被入侵了顯得至關重要,個人結……
  • 如何優化Kubernetes集群?看看這五個維度
    1閱讀 0條評論 個贊
    一、節點配額和內核參數調整對于公有云上的Kubernetes集群,規模大了之后很容器碰到配額問題,需要提前在云平臺上增大配額。這些需要增大的配額包括:虛擬機個數vCPU個數內網IP地址個數公……
  • 45 Git經典操作場景 獨家處理不會匹配的代碼
    0閱讀 0條評論 個贊
    文章轉載于:江南一點雨git對于大家應該都不太陌生,熟練使用git已經成為程序員的一項基本技能,盡管在工作中有諸如Sourcetree這樣牛X的客戶端工具,使得合并代碼變的很方便。但找工作面試和一些……
  • 數據標準和數據規范的區別?
    1閱讀 0條評論 個贊
    彭友們好,我是老彭呀。前兩天有個彭友問我:到底數據標準和數據規范有啥區別?這哥們可不是小白,他是十幾年的老數據人了,最近在做集團數據管理體系設計,寫文檔都寫到使勁揪頭發。原本烏黑濃密的秀發,現在快揪成禿子了?!?/div>
  • 數據治理:說起來容易做起來難?
    3閱讀 0條評論 個贊
    以下文章來源于談數據,作者石秀峰“數據治理”這個10多年前就已經出現的名稱,在最近這幾年時間一下子火了起來。不知何時,江湖中流傳出了:“數字轉型、治理先行”的說法。于是乎,我們看到:不僅是傳統提供數據……
  • 寫下一個在線事件的循環依賴問題
    1閱讀 0條評論 個贊
    前情回顧一探Spring的循環依賴,源碼詳細分析→真的非要三級緩存嗎中講到了循環依賴問題同樣說明了Spring只能解決setter方式的循環依賴,不能解決構造方法的循環依賴重點介紹了Spring是如何解決setter方式的循環依賴,感興趣的可以去看下二探既然Spring不能解決構造方法的循環依賴……
  • 5大步驟10個案例 堪稱SQL優化的萬能公式
    1閱讀 0條評論 個贊
    作者丨狼爺來源丨網址:https://www.cnblogs.com/powercto/p/14410128.html一、前言在應用開發的早期,數據量少,開發人員開發功能時更重視功能上的實現,隨著生產……
  • PostgreSQL統計和性能優化深入分析
    1閱讀 0條評論 個贊
    基本關系級別的統計信息存儲在pg_class系統目錄的表中。統計數據包括以下數據:關系的行數(reltuples)。關系的頁面大小(relpages)。在關系的可見性圖中標記的頁面數(relallvisible)。SELECTreltuples,relpages,relallvisibleFROMp……
  • OS接近度:Linux時間可能沒有你想的那么靠譜!
    1閱讀 0條評論 個贊
    原創:小姐姐味道(微信公眾號ID:xjjdog),歡迎分享,非公眾號轉載請保留此聲明。如果你想周期性的做一些事情,那么必然,會與時間產生聯系。比如,每天早晨7點吃早餐,每天晚上10點進入夢鄉。當然,如……
  • 談Java并發下的樂觀鎖
    1閱讀 0條評論 個贊
    引子各位少俠大家好!今天我們來聊聊Java并發下的樂觀鎖。在聊樂觀鎖之前,先給大家復習一個概念:原子操作:什么是原子操作呢?我們知道,原子(atom)指化學反應不可再分的基本微粒。在Java多……
  • 2022年前端技術發展趨勢綜述
    3閱讀 0條評論 個贊
    “天下大勢,浩浩湯湯,順之者昌,逆之者亡?!币韵率菍η岸烁魑淮罄?021總結的一個匯總總結。希望可以看到一些前端行業的動向,排布。幫助團隊和自身制定未來的規劃。內容分為四個部分:基礎框架/工程化語言行……
  • 有了這個Docker網絡原理 我徹底愛死了~
    1閱讀 0條評論 個贊
    Docker網絡原理容器是相對獨立的環境,相當于一個小型的Linux系統,外界無法直接訪問,那他是怎么做的呢,這里我們先了解下Linuxvethpair。1.Linuxvethpai……
  • 基于DDD思想的技術架構戰略調整
    0閱讀 0條評論 個贊
    作者介紹PROFILE鄭吉敏2019年8月入職去哪兒網,機票目的地事業群技術總監、技術委員會委員、業務架構SIG負責人,負責酒店報價中心團隊、業務架構組。2020年金項獎評選中主導的“對內DD……
  • 復制粘貼代碼很可能帶來災難性的后果
    1閱讀 0條評論 個贊
    作者|Entreprogrammer譯者|Sambodhi策劃|凌敏很多人都有過復制粘貼代碼的經歷,但如果你經常盲目地復制粘貼代碼,甚至是復制粘貼自己不理解的代碼,很可能會帶來災難性的后果……
  • 用SQL查找三列異常值的四種方法
    1閱讀 0條評論 個贊
    前兩天在抽一段數據時,碰到一個典型問題,初一想,有很多解法,所以特想做一次歸納?;叵胪?,其實有好些想法,可以深究,因沒及時記錄,事后就再也想不起來,白白浪費好多這樣的機會。所以為了不留遺憾,今天沉下心來,好好復盤下?!?/div>
最近發布資訊
更多
十八禁试看120秒做受