ES5 getter setter

? ? 最近在學習vuejs,了解到內部實現使用到了es5的Getters和Setters。之前看高程的時候,沒有重視這塊,今天查看一下文檔,了解了他們的作用,再次記錄一下,可供以后查看和共享。

  定義Getters和Setters:(一共有三種定義方法)

 第一種方法: 使用對象字面量創建對象時,可以像下面定義set 和set一樣定義,

 1 var obj = {
 2     "a": 1,
 3     get b(){
 4         return this.a + 1;
 5     },
 6     set c(val){
 7         this.a = val + this.a;
 8     }
 9 };
10 
11 console.log(obj.a);   //初始值為1
12 console.log(obj.b);   //2
13 obj.c = 3;
14 console.log(obj.a);   //4

  第二種方法:通過Object.defineProperty(...)來定義

 1 var d = Date.prototype;
 2 
 3 Object.defineProperty(d, "year", {
 4     get : function() {
 5         return this.getFullYear();
 6     },
 7     set: function(val) {
 8         this.setFullYear(val);
 9     }
10 });
11 
12 var date = new Date();
13 console.log("*********");
14 console.log(date.year);   //2016
15 console.log("*********");

第三種方式:

 1 function Filed(val){
 2     var value = val;
 3     this.getValue = function(){
 4         return value;
 5     };
 6     this.setValue = function(val){
 7         value = value = val;
 8     };
 9 }
10 
11 var f = new Filed(20);
12 console.log("\n**********************");
13 console.log(f.getValue());         //20
14 f.setValue(30);
15 console.log(f.getValue());         //30

Getters和Setters可以做什么?

  目的:給js語言增加覆蓋對象單個屬性默認的[[Get]]和[[Put]]能力。

  實際上,Getters和Setters都是對象上的屬性,通過Getters可以調用對象上隱藏的函數來獲取值,通過Setters調用隱藏的函數,來為對象屬性賦值。

  我們知道對象的屬性描述符有value、writable、configurable和enumerable。Getters和Setter也可被理解為對象的存取描述符。如果一個對象定義了Getter和Setter,value和writable會被忽略,js只考慮Getter、Setter、configurable和enumerable。

  

 1 var obj = {
 2     get a(){
 3         return 2;
 4     }
 5 };
 6 
 7 Object.defineProperty(obj, "b", {
 8     get: function(){
 9         return this.a * 4;
10     },
11     enumerable: true
12 });
13 
14 console.log(obj.a);   //2
15 console.log(obj.b);   //8
16 obj.a = 4;
17 console.log(obj.a);   //2

  在16行的時候,我們對a進行賦值,但是在17行的時候,依舊輸出了2,,這是因為一旦存在存在存取描述符,并且僅設有Getter的話(即便設有Setter),對該屬性的賦值會被默認忽略。

 1 var obj = {
 2     get a(){
 3         return 2;
 4     },
 5     set c(val){
 6         this.a = 3;
 7     }
 8 };
 9 
10 Object.defineProperty(obj, "b", {
11     get: function(){
12         return this.a * 4;
13     },
14     enumerable: true
15 });
16 
17 console.log(obj.a);   //2
18 console.log(obj.b);   //8
19 //obj.a = 4;
20 obj.c = 4;
21 console.log(obj.a);   //2

  實際使用代碼如下:

 1 var myObject = {
 2     // define a getter for `a`
 3     get a() {
 4         return this._a_;
 5     },
 6 
 7     // define a setter for `a`
 8     set a(val) {
 9         this._a_ = val * 2;
10     }
11 };
12 
13 myObject.a = 2;
14 
15 console.log(myObject.a); // 4

  通過Setter和Getter,我們可以動態設置和獲取對象屬性的值得效果:

 1 var expr = "foo";
 2 var obj = {
 3     a: "aa",
 4     set [expr](val){
 5         this.a = val;
 6     },
 7     get [expr](){
 8         return expr
 9     }
10 };
11 
12 obj.foo="bb";
13 console.log(obj.a);   //bb
14 console.log(obj[expr]);   //foo

對于上面的動態設置和獲取,不曉得實際用途。

js的[[Get]]和[[Put]]操作

Getter和Setter會對js對象屬性的存取產生怎樣的影響呢?

[[Get]]操作:

1 var obj = {
2     a: 2  
3 };
4 console.log(obj.a);    //2

上面代碼的背后的機制:

執行的時候,JavaScript 會在對象 obj上執行一次 [[Get]] 操作。JavaScript 內置的 [[Get]] 操作首先根據屬性名稱檢查對象本身是否有該屬性,如果這時候找到了,那么就返回它的值;如果沒找到,那么會通過該對象的Prototype?鏈繼續向上查找,直到頂層的?Object.prototype。見下面代碼:

1 var OldObj = function(){};
2 OldObj.prototype.a = 2;
3 var obj = new OldObj();
4 console.log(obj.a);   //2

[[put]]操作:

1 var obj = {
2     a: 2  
3 };
4 obj.a = 3;

背后的機制:

首先,JavaScript 會觸發一個 [[Put]] 操作,它的行為會根據要賦值的屬性是否已經直接存在于該對象上而有所不同。如果該屬性已經存在了,[[Put]] 操作會執行如下步驟:

  1. 該屬性是否已經定義了?Setter,如果已經定義了,那么調用它;
  2. 該屬性的屬性描述符 (Property Descriptor)是否定義了?writable: false,如果是,那么賦值操作被忽略,如果是?strict mode,那么會拋出?TypeError?異常;
  3. 如果沒有上述情況,那么給已存在的屬性賦值。

如果被賦值的屬性不是直接存在于對象上:

  1. [[Put]] 操作首先會搜索?Prototype?鏈,如果沒有找到?foo,那么就在被賦值的對象上直接創建?foo,并賦值為?bar
  2. 如果在?Prototype?鏈上找到了?foo,代碼的行為就會變得詭異起來,我們回頭再看。在此之前,先來了解一個概念,叫做變量隱藏 (Variable Shadowing)。當一個變量既直接存在于對象本身,又存在于對象的?Prototype?鏈,那我們就可以說對象本身的屬性?foo?隱藏了存在于?Prototype?鏈的變量?foo。理解了這個概念,我們再來看當變量?foo?在?Prototype?鏈上存在的的時候,給?foo?賦值可能帶來的三種結果:
    1. 如果?foo?在?Prototype?鏈上存在,并且它沒有被定義為只讀的 (writable: false),那么一個名叫?foo?的屬性會被直接添加到?myObject,從而造成?變量隱藏 (Shadowing)
    2. 如果?foo?在?Prototype?鏈上存在,并且被標記為只讀的 (writable: false),那么對?foo?的賦值操作會被忽略;如果是?strict mode,那么會拋出異常;
    3. 如果?foo?在?Prototype?鏈上存在,并且它具有?Setter,那么?Setter?始終會被調用,也就是說沒有屬性會被直接添加到?myObject?上,也不會發生變量隱藏。也許你還記得,當對象屬性?Setter?存在的時候,給該屬性賦值,不會檢查?writable

原文地址:js Getters和Setters

轉載于:https://www.cnblogs.com/yanyalun/p/5549883.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/271697.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/271697.shtml
英文地址,請注明出處:http://en.pswp.cn/news/271697.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python 調用bat失敗_要想順利通過Python面試,你最起碼需要達到白銀段位!

近幾年 Python 非常熱門,在學術界和產業界的使用率顯著提高。目前學習Python的人數日益增多,Python在近3年的編程語言受歡迎度中一直處于榜首。今天我們就來講講在產業界,需要具備哪些能力才能獲得一個滿意的 Python 相關崗位 Offer。Python基…

多線程售票demo,用ReentrantLock實現

代碼: public class TicketReentLockDemo implements Runnable {private int ticketTotal 100;private Lock lock new ReentrantLock();Overridepublic void run() {while (ticketTotal > 0) {try {lock.lock();if (ticketTotal > 0) {try {TimeUnit.MILLISECONDS.sle…

在linux安裝不了apache,Apache 不能安裝在linux?

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓官網下載了tar.gz的文件, 然后tar解壓, 可是走到 ./configureprefix/usr/local/apache/ 的時候就開始出現一些“NO”我怕這樣make會有問題, 請問大家碰到出現"no"的選項嘛?…

andriod sqlite 詳解轉載

SQLite簡介 Google為Andriod的較大的數據處理提供了SQLite,他在數據存儲、管理、維護等各方面都相當出色,功能也非常的強大。SQLite具備下列特點: 1.輕量級 使用 SQLite 只需要帶一個動態庫,就可以享受它的全部功能,而…

數據庫:SQLServer中in和 exists函數用法筆記

今天給大家分享一下SQLServer中in和 exists 用法,希望能對大家有所幫助。一、IN 用法確定指定的值是否與子查詢或列表中的數據相匹配。1.1 語法格式test_expression [ NOT ] IN ( subquery | expression [ ,...n ] )1.2 參數說明test_expression為任意有…

什么是m叉樹_不懂數據庫索引的底層原理?那是因為你心里沒點b樹

前幾天下班回到家后正在處理一個白天沒解決的bug,廁所突然傳來對象的聲音: 對象:xx,你有《時間簡史》嗎? 我:我去!妹子,你這啥癖好啊,我有時間也不會去撿屎啊&#xff01…

可重入鎖是什么和demo

可重入鎖 reentrantlock是獨占鎖且可重入的 synchronized 也可以重入 可重入意思就是這個線程已經獲取鎖了,你再獲取該鎖還能獲取 獲取的還是原來的鎖 不會出現問題 可以降低編程難度 代碼如下: new Thread(new Runnable() {Overridepublic void run() {synchr…

linux 安裝python 3.x,Linux 安裝python3.x步驟

本文轉發自博客園非真的文章,內容略有改動linux系統本身默認安裝有2.x版本的python,版本x根據不同版本系統有所不同,通過python --V 或 python --version 查看系統自帶的python版本。有一些系統命令時需要用到python2,不能卸載&am…

數據庫:SQLServer中游標的用法筆記

一、游標的概念知識游標可以理解為SQL Server的一種數據訪問機制,它允許用戶訪問數據的維度是數據行。用戶可以對每一行數據進行單獨處理,從而降低系統開銷和潛在的阻隔情況,游標主要用于存儲過程,觸發器和 T_SQL復雜的腳本中&…

BZOJ_1009_[HNOI2008]_GT考試_(動態規劃+kmp+矩陣乘法優化+快速冪)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id1009 字符串全部由0~9組成,給出一個串s,求一個長度為n的串,不包含s的種類有多少. 分析 第一眼以為是組合.然后更滑稽的是用錯誤的方法手算樣例居然算出來是對的...我數學是有多差... 題解也是看了好半天,有點難理解. 感覺…

智慧政務解決方案(28頁)pdf_【金眾電子】智慧政務解決方案

智慧政務解決方案立式黨建廣告機廣告機簡介:KC-立式政務廣告機(室內/室外可選)液晶屏幕特別賣點:安裝簡易、亮度調節、實時更新、傳輸安全應用場所:各種需要文化傳播的政務機構、政府機關、會議場所等。雙立柱政務文化欄/宣傳欄文化欄簡介&am…

笨辦法學linux dhcp,了解網關、DNS、子網掩碼、MAC地址、DHCP

原標題:了解網關、DNS、子網掩碼、MAC地址、DHCP什么是網關、DNS、子網掩碼,它有什么作用,確實,我們平時在網絡中總是在不斷的提到網關,卻很少真正的去了解它。一、什么是網關1、什么是網關網關是一種充當轉換重任的計…

數據庫:SQLServer Stuff 函數用法筆記

今天小編給大家分享一下自己整理一下SQLServer Stuff函數用法技巧和常用示例,有需要的朋友可以學習一下。一、Stuff函數的作用1.1官方解釋STUFF 函數將字符串插入到另一個字符串中。 它從第一個字符串的開始位置刪除指定長度的字符;然后將第二個字符串插…

自定義注解,aop實現注解鎖

多線程環境下,會出現線程不安全的問題,所以要對某些方法加鎖以保證線程安全 但是如果方法過多,每個方法前后都加這么一句,有點麻煩了,而且代碼可讀性也會差一些。可以使用aop切面編程,對某些加有特定注解&…

Android——實現歡迎界面的自動跳轉(轉)

Android實現歡迎界面的自動跳轉,就是打開某一個安卓手機應用,出現的歡迎界面停留幾秒鐘,自動進入應用程序的主界面。在網上看到很多種實現辦法,但是感覺這種方法還是比較簡單的。 在onCreate里設置個Timer,然后建立Int…

手機端刷recovery工具_MIUI/REDMIN手機玩機匯集

愿你刷機半生歸來仍是MIUI1解鎖篇解鎖Bootloader準備工作:1.手機備份數據2.手機進入開發者模式①進入“設置 -> 我的設備 -> 全部參數"中連續點擊MIUI版本,進入”開發者模式“②進入“設置 -> 開發者選項 -> 設備解鎖狀態”中綁定賬號和…

數據結構基礎:線性表學習筆記

1、線性表定義線性表是指n個元素的有限序列(n>0),通常用(a1,a2,a3...,an),來表示。2、線性表特點1、存在唯一的一個首元素2、存在唯一一個尾元素3、除第首元素外,每個元素只有一個直接前驅。4、除尾元素外,每個元素只有一個直接后繼。3、線性表的存儲…

c語言流水燈小程序,流水燈小程序.doc

流水燈小程序流水燈小程序#include void delay() //延時函數&#xff0c;這里延時100ms{int i,j;for(i0;i<100;i){for(j0;j<2242;j){} //j循環一次大概1ms}}void main(){ //這里看LED原理圖LPC_IOCON->JTAG_TMS_PIO1_00x01;//定義p1.0引腳為輸出LPC_IOCON->JTAG_TD…

iphone導出照片到電腦_iPhone里的照片如何快速導入電腦

前幾日我一好友發微信問我&#xff1a;“向陽&#xff0c;我手機里有一萬多張照片&#xff0c;怎么能快速的備份到電腦里&#xff1f;”我一看這問題&#xff0c;確實很多果友從用蘋果手機開始&#xff0c;機器已經更新換代了好多代了&#xff0c;照片是越來越多&#xff0c;內…