《你不知道的js(上卷)》筆記2(this和對(duì)象原型)

書(shū)籍封面

學(xué)了多種語(yǔ)言狼忱,發(fā)現(xiàn)javascriptthis是最難以捉摸的摊崭。this不就是指向當(dāng)前對(duì)象的指針嗎垮衷?可是結(jié)合上下文來(lái)看,卻又往往不知道this到底指的是誰(shuí)了惶室,所以Javascript最主要的兩個(gè)知識(shí)點(diǎn)温自,除了閉包玄货,就是this了。

1. 關(guān)于this

this關(guān)鍵字是javascript中最復(fù)雜的機(jī)制之一悼泌。它是一個(gè)很特別的關(guān)鍵字松捉,被自動(dòng)定義在 所有函數(shù)的作用域中。

this提供了一種更優(yōu)雅的方式來(lái)隱式“傳遞”一個(gè)對(duì)象引用馆里,因此可以將API設(shè)計(jì)
得更加簡(jiǎn)潔并且易于復(fù)用隘世。

function identify() {
  return this.name.toUpperCase();
}

var me = {
  name: "Kyle"
};

identify.call( me ); // KYLE

this并不像我們所想的那樣指向函數(shù)本身。

function foo(num) {
  this.count++;
}

foo.count = 0;
var i;
for (i=0; i<10; i++) { 
      if (i > 5) {
        foo( i ); 
      }
}
console.log( foo.count ); // 0 

函數(shù)內(nèi)部代碼this.count中的this并不是指向那個(gè)函數(shù)對(duì)象鸠踪,所以雖然屬性名相同丙者,根對(duì)象卻并不相同,困惑隨之產(chǎn)生营密。

函數(shù)內(nèi)部代碼this.count最終值為NaN械媒,同時(shí)也是全局變量。

可以使用函數(shù)名稱標(biāo)識(shí)符來(lái)代替this來(lái)引用函數(shù)對(duì)象评汰。這樣纷捞,更像是靜態(tài)變量。

function foo(num) {
  foo.count++;
}

foo.count = 0;
var i;
for (i=0; i<10; i++) { 
      if (i > 5) {
        foo( i ); 
      }
}
console.log( foo.count ); // 4

另外一種方式是強(qiáng)制this指向foo函數(shù)對(duì)象被去。

function foo(num) {
  this.count++;
}

foo.count = 0;
var i;
for (i=0; i<10; i++) { 
      if (i > 5) {
        foo.call(foo, i ); 
      }
}
console.log( foo.count ); // 4

this到底是什么

this是在運(yùn)行時(shí)進(jìn)行綁定的主儡,并不是在編寫(xiě)時(shí)綁定,它的上下文取決于函數(shù)調(diào) 用時(shí)的各種條件惨缆。this的綁定和函數(shù)聲明的位置沒(méi)有任何關(guān)系糜值,只取決于函數(shù)的調(diào)用方式。

調(diào)用位置

函數(shù)被調(diào)用的位置坯墨。每個(gè)函數(shù)的 this 是在調(diào)用 時(shí)被綁定的寂汇,完全取決于函數(shù)的調(diào)用位置,因?yàn)樗鼪Q定了this的綁定畅蹂。

function baz() {
// 當(dāng)前調(diào)用棧是:baz
// 因此健无,當(dāng)前調(diào)用位置是全局作用域
   console.log( "baz" );
    bar(); // <-- bar 的調(diào)用位置 
}

function bar() {
    // 當(dāng)前調(diào)用棧是 baz -> bar
    // 因此,當(dāng)前調(diào)用位置在 baz 中
    console.log( "bar" );
    foo(); // <-- foo 的調(diào)用位置 
}

function foo() {
        // 當(dāng)前調(diào)用棧是 baz -> bar -> foo 
        // 因此液斜,當(dāng)前調(diào)用位置在 bar 中
         console.log( "foo" );
}
baz(); // <-- baz 的調(diào)用位置

1.1 綁定規(guī)則

默認(rèn)綁定

聲明在全局作用域中的變量就是全局對(duì)象的一個(gè)同名屬性累贤。

function foo() { 
  console.log( this.a );
}

var a = 2; 
foo(); // 2

在本 例中,函數(shù)調(diào)用時(shí)應(yīng)用了this的默認(rèn)綁定少漆,因此this指向全局對(duì)象臼膏。

foo()是直接使用不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用的,因此只能使用默認(rèn)綁定示损,無(wú)法應(yīng)用其他規(guī)則渗磅。

如果使用嚴(yán)格模式,那么全局對(duì)象將無(wú)法使用默認(rèn)綁定,因此this會(huì)綁定到 undefined始鱼。

function foo() {
   "use strict";
    console.log( this.a );
}
var a = 2;
foo(); // TypeError: this is undefined

隱式綁定

如果調(diào)用位置是有上下文對(duì)象仔掸,或者被某個(gè)對(duì)象擁有或者包含,那么就可能隱式綁定医清。

function foo() { 
  console.log( this.a );
}
var obj = { 
  a: 2,
  foo: foo
};

var obj1 = { 
  a: 42,
  obj: obj
};

obj.foo(); // 2
obj1.obj.foo(); // 2

當(dāng)函數(shù)引用有上下文對(duì)象時(shí)起暮,隱式綁定規(guī)則會(huì)把函數(shù)調(diào)用中的this綁定到這個(gè)上下文對(duì)象。因?yàn)檎{(diào) 用foo()時(shí)this被綁定到obj会烙,因此this.aobj.a是一樣的负懦。

對(duì)象屬性引用鏈中只有最頂層或者說(shuō)最后一層會(huì)影響調(diào)用位置。

隱式綁定的函數(shù)可能會(huì)丟失綁定對(duì)象柏腻,而應(yīng)用默認(rèn)綁定纸厉,把this綁定到全局對(duì)象或者undefined上,取決于是否是嚴(yán)格模式五嫂。

function foo() { 
  console.log( this.a );
}
var obj = { 
  a: 2,
  foo: foo 
};
var bar = obj.foo; // 函數(shù)別名!
var a = "oops, global"; // a 是全局對(duì)象的屬性 
bar(); // "oops, global"

function doFoo(fn) {
    // fn 其實(shí)引用的是 foo 
  fn(); // <-- 調(diào)用位置!
}

doFoo( obj.foo ); // "oops, global"

barobj.foo的一個(gè)引用颗品,bar()其實(shí)是一個(gè)不帶任何修飾的函數(shù)調(diào)用。

參數(shù)傳遞其實(shí)就是一種隱式賦值沃缘,因此我們傳入函數(shù)時(shí)也會(huì)被隱式賦值抛猫,所以結(jié)果一樣。

顯式綁定

可以使用函數(shù)的call(..)apply(..)方法實(shí)現(xiàn)顯式綁定孩灯。

function foo() { 
  console.log( this.a );
}
var obj = {
   a:2
};
foo.call( obj ); // 2

如下例子,無(wú)論bar綁定到哪個(gè)對(duì)象上逾滥,foo始終綁定在obj上峰档,稱之為硬綁定。

function foo() { 
  console.log( this.a );
}
var obj = { 
  a:2
};
var bar = function() { 
  foo.call( obj );
};

bar.call( window ); // 2

在 ES5 中提供了內(nèi)置的方法Function.prototype.bind就是硬綁定寨昙。

如果你把null或者undefined作為this的綁定對(duì)象傳入call讥巡、apply或者 bind,這些值在調(diào)用時(shí)會(huì)被忽略舔哪,實(shí)際應(yīng)用的是默認(rèn)綁定規(guī)則欢顷。

new綁定

JavaScriptnew的機(jī)制實(shí) 際上和面向類(lèi)的語(yǔ)言完全不同。

JavaScript中捉蚤,構(gòu)造函數(shù)只是一些 使用new操作符時(shí)被調(diào)用的函數(shù)抬驴。它們并不會(huì)屬于某個(gè)類(lèi),也不會(huì)實(shí)例化一個(gè)類(lèi)缆巧。實(shí)際上布持,它們甚至都不能說(shuō)是一種特殊的函數(shù)類(lèi)型,它們只是被 new 操作符調(diào)用的普通函數(shù)而已陕悬。

使用new來(lái)調(diào)用函數(shù)题暖,或者說(shuō)發(fā)生構(gòu)造函數(shù)調(diào)用時(shí),會(huì)自動(dòng)執(zhí)行下面的操作。

  1. 創(chuàng)建(或者說(shuō)構(gòu)造)一個(gè)全新的對(duì)象胧卤。

  2. 這個(gè)新對(duì)象會(huì)被執(zhí)行[[原型]]連接唯绍。

  3. 這個(gè)新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this。

  4. 如果函數(shù)沒(méi)有返回其他對(duì)象枝誊,那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對(duì)象况芒。

function foo(p1,p2) { 
  this.val = p1 + p2;
}
// 之所以使用 null 是因?yàn)樵诒纠形覀儾⒉魂P(guān)心硬綁定的 this 是什么 
// 反正使用 new 時(shí) this 會(huì)被修改
var bar = foo.bind( null, "p1" );
var baz = new bar( "p2" ); 
baz.val; // p1p2

綁定規(guī)則優(yōu)先級(jí):new綁定 > 顯式綁定 > 隱式綁定 > 默認(rèn)綁定

箭頭函數(shù)無(wú)法使用以上四種綁定規(guī)則。

function foo() {
// 返回一個(gè)箭頭函數(shù) 
  return (a) => {
    //this 繼承自 foo()
    console.log( this.a ); 
  };
}

var obj1 = { 
  a:2
};

var obj2 = { 
  a:3
};

var bar = foo.call( obj1 );
bar.call( obj2 ); // 2

2. 對(duì)象

對(duì)象的兩種形式定義:聲明(文字)形式和構(gòu)造形式侧啼。

var myObj = { 
  key: value
  // ... 
};

var myObj = new Object(); 
myObj.key = value;

六種主要類(lèi)型: string,number,boolean,null,undefined,object

object外的5種類(lèi)型為簡(jiǎn)單基本類(lèi)型牛柒,本身并不是對(duì)象,但是typeof null會(huì)返回字符串 "object"痊乾。

內(nèi)置對(duì)象:String,Number,Boolean,Object,Function,Array,Date,RegExp,Error

var strPrimitive = "I am a string"; 
typeof strPrimitive; // "string" 
strPrimitive instanceof String; // false

var strObject = new String( "I am a string" ); 
typeof strObject; // "object"
strObject instanceof String; // true
// 檢查 sub-type 對(duì)象
Object.prototype.toString.call( strObject ); // [object String]

在必要時(shí)語(yǔ)言會(huì)自動(dòng)把字符串字面量轉(zhuǎn)換成一個(gè)String對(duì)象皮壁,可以訪問(wèn)屬性和方法。

對(duì)于Object哪审、Array蛾魄、FunctionRegExp來(lái)說(shuō),無(wú)論使用文字形式還是構(gòu) 造形式湿滓,它們都是對(duì)象滴须,不是字面量。

屬性

屬性名永遠(yuǎn)是字符串叽奥,雖然在數(shù)組下標(biāo)中使用的的確是數(shù)字扔水,但是在對(duì)象屬性名中數(shù)字會(huì)被轉(zhuǎn)換成字符串。

ES6 增加了可計(jì)算屬性名,最常用的場(chǎng)景可能是 ES6 的符號(hào)(Symbol)朝氓。

var prefix = "foo";
var myObject = {
  [prefix + "bar"]:"hello", 
  [prefix + "baz"]: "world"
};
     
myObject["foobar"]; // hello
myObject["foobaz"]; // world

如果你試圖向數(shù)組添加一個(gè)屬性魔市,但是屬性名“看起來(lái)”像一個(gè)數(shù)字,那它會(huì)變成 一個(gè)數(shù)值下標(biāo)

var myArray = [ "foo", 42, "bar" ]; 
myArray["3"] = "baz"; 
myArray.length; // 4
myArray[3]; // "baz"

復(fù)制對(duì)象

對(duì)于JSON安全的對(duì)象來(lái)說(shuō)赵哲,有一種巧妙的復(fù)制方法:

var newObj = JSON.parse( JSON.stringify( someObj ) );

ES6 定義了Object.assign(..)方法來(lái)實(shí)現(xiàn)淺復(fù)制待德。

屬性描述符

三個(gè)特性:writable(可寫(xiě))、 enumerable(可枚舉)和 configurable(可配置)枫夺。

var myObject = { 
  a:2
};

Object.getOwnPropertyDescriptor( myObject, "a" );
// {
// value: 2,
// writable: true,
// enumerable: true,
// configurable: true 
// }

在創(chuàng)建普通屬性時(shí)屬性描述符會(huì)使用默認(rèn)值将宪,我們也可以使用 Object.defineProperty(..)來(lái)添加一個(gè)新屬性或者修改一個(gè)已有屬性(如果它是configurable)并對(duì)特性進(jìn)行設(shè)置。

var myObject = {};
     Object.defineProperty( myObject, "a", {
         value: 2,
         writable: true, 
         configurable: true, 
         enumerable: true
     } );
     myObject.a; // 2

writable決定是否可以修改屬性的值橡庞,如果在嚴(yán)格模式下较坛,這 種方法會(huì)出錯(cuò)(TypeError)。

configurable修改成 false 是單向操作毙死,無(wú)法撤銷(xiāo)!不管是不是處于嚴(yán)格模式燎潮,嘗 試修改一個(gè)不可配置的屬性描述符都會(huì)出錯(cuò)(TypeError)。

屬性是不可配置時(shí)使用 delete也會(huì)失敗扼倘。

如果把enumerable設(shè)置成false确封,這個(gè)屬性就不會(huì)出現(xiàn)在枚舉中(比如for..in循環(huán))除呵,雖然仍 然可以正常訪問(wèn)它。

不變性

常量: 結(jié)合writable:falseconfigurable:false就可以創(chuàng)建一個(gè)真正的常量屬性(不可修改爪喘、 重定義或者刪除)

var myObject = {};
     Object.defineProperty( myObject, "FAVORITE_NUMBER", {
         value: 42,
          writable: false,
          configurable: false 
      });

禁止擴(kuò)展: 如果你想禁止一個(gè)對(duì)象添加新屬性并且保留已有屬性颜曾,可以使用Object.preventExtensions(..)

密封: Object.seal(..) 會(huì)創(chuàng)建一個(gè)“密封”的對(duì)象,這個(gè)方法實(shí)際上會(huì)在一個(gè)現(xiàn)有對(duì)象上調(diào)用Object.preventExtensions(..) 并把所有現(xiàn)有屬性標(biāo)記為configurable:false秉剑。

凍結(jié): Object.freeze(..)會(huì)創(chuàng)建一個(gè)凍結(jié)對(duì)象泛豪,這個(gè)方法實(shí)際上會(huì)在一個(gè)現(xiàn)有對(duì)象上調(diào)用Object.seal(..)并把所有“數(shù)據(jù)訪問(wèn)”屬性標(biāo)記為writable:false,這樣就無(wú)法修改它們 的值侦鹏。

get和set

var myObject = {
// 給 a 定義一個(gè) getter 
  _a:2,
  get a() {
    return this.a; 
  },
// 給 a 定義一個(gè) setter 
  set a(_a){
     this._a = _a;
  }
};

Object.defineProperty( 
  myObject, // 目標(biāo)對(duì)象 
   "b", // 屬性名
  {
  // 描述符
  // 給 b 設(shè)置一個(gè) getter
  get: function(){ 
      return this.a * 2 
    },
      // 確保 b 會(huì)出現(xiàn)在對(duì)象的屬性列表中
     enumerable: true
    }
);

myObject.a; // 2
myObject.b; // 4

在不訪問(wèn)屬性值的情況下判斷對(duì)象中是否存在這個(gè)屬性:

var myObject = { 
  a:2
};
 ("a" in myObject); // true
("b" in myObject); // false
myObject.hasOwnProperty( "a" ); // true
myObject.hasOwnProperty( "b" ); // false

in操作符會(huì)檢查屬性是否在對(duì)象及其 [[Prototype]] 原型鏈中诡曙,相比之下,hasOwnProperty(..)只會(huì)檢查屬性是否在 myObject 對(duì)象中略水,不會(huì)檢查 [[Prototype]] 鏈价卤。

有的對(duì)象可能沒(méi)有連接到Object.prototype,可以使用Object.prototype.hasOwnProperty. call(myObject,"a")進(jìn)行判斷渊涝。

propertyIsEnumerable(..)會(huì)檢查給定的屬性名是否直接存在于對(duì)象中(而不是在原型鏈 上)并且滿足enumerable:true慎璧。

Object.keys(..)會(huì)返回一個(gè)數(shù)組,包含所有可枚舉屬性跨释,Object.getOwnPropertyNames(..)會(huì)返回一個(gè)數(shù)組胸私,包含所有屬性,無(wú)論它們是否可枚舉鳖谈。

數(shù)組有內(nèi)置的@@iterator岁疼,因此for..of可以直接應(yīng)用在數(shù)組上。

var myArray = [ 1, 2, 3 ];
var it = myArray[Symbol.iterator]();
it.next(); // { value:1, done:false } 
it.next(); // { value:2, done:false } 
it.next(); // { value:3, done:false } 
it.next(); // { done:true }

手動(dòng)定義@@iterator:

var myObject = { a: 2,
b: 3 };
Object.defineProperty( myObject, Symbol.iterator, { 
  enumerable: false,
  writable: false,
  configurable: true,
  value: function() { 
      var o = this;
      var idx = 0;
      var ks = Object.keys( o ); 
       return {
          next: function() { 
                return {
                         value: o[ks[idx++]],
                         done: (idx > ks.length)
                     };
        } };
} } );

3. 原型

JavaScript中的對(duì)象有一個(gè)特殊的 [[Prototype]] 內(nèi)置屬性缆娃,其實(shí)就是對(duì)于其他對(duì)象的引用五续。幾乎所有的對(duì)象在創(chuàng)建時(shí) [[Prototype]] 屬性都會(huì)被賦予一個(gè)非空的值。

對(duì)于默認(rèn)的 [[Get]] 操作來(lái)說(shuō)龄恋,第一步是檢查對(duì)象本身是 否有這個(gè)屬性,如果有的話就使用它凶伙。但是如果不存在與對(duì)象本身郭毕,就需要會(huì)繼續(xù)訪問(wèn)對(duì)象的 [[Prototype]] 鏈。

var anotherObject = { 
  a:2
};
// 創(chuàng)建一個(gè)關(guān)聯(lián)到 anotherObject 的對(duì)象
var myObject = Object.create( anotherObject ); 
myObject.a; // 2

任何可以通過(guò)原型鏈訪問(wèn)到并且是enumerable的屬性都會(huì)被枚舉函荣。

使用in操作符來(lái)檢查屬性在對(duì)象中是否存在時(shí)显押,同樣會(huì)查找對(duì)象的整條原型鏈(無(wú)論屬性是否可枚舉)。

所有普通的 [[Prototype]] 鏈最終都會(huì)指向內(nèi)置的Object.prototype傻挂,它包含 JavaScript中許多通用的功能乘碑,比如.toString()

原型鏈上層時(shí)myObject.foo = "bar"會(huì)出現(xiàn)的三種情況:

  • 如果[[Prototype]]鏈上層存在名為foo的普通數(shù)據(jù)訪問(wèn)屬性并且不是只讀方篮,就會(huì)直接在 myObject 中添加一個(gè)名為 foo 的新 屬性凳怨,它是屏蔽屬性。

  • 如果[[Prototype]]鏈上層存在名為foo的普通數(shù)據(jù)訪問(wèn)屬性并且只讀像屋,則無(wú)法修改已有屬性或者在 myObject 上創(chuàng)建屏蔽屬性资铡。

  • 如果在[[Prototype]]鏈上層存在foo并且它是一個(gè)setter电禀,那就一定會(huì) 調(diào)用這個(gè) setter

有些情況下會(huì)隱式產(chǎn)生屏蔽:

var anotherObject = { 
  a:2
};
var myObject = Object.create( anotherObject );
anotherObject.a; // 2
myObject.a; // 2

anotherObject.hasOwnProperty( "a" ); // true
myObject.hasOwnProperty( "a" ); // false
myObject.a++; // 隱式屏蔽! 
anotherObject.a; // 2
myObject.a; // 3
myObject.hasOwnProperty( "a" ); // true

++操作首先會(huì)通過(guò) [[Prototype]] 查找屬性a并從anotherObject.a獲取當(dāng)前屬性值2笤休,然后給這個(gè)值加1尖飞,接著用 [[Put]] 將值3賦給myObject中新建的屏蔽屬性a

類(lèi)

所有的函數(shù)默認(rèn)都會(huì)擁有一個(gè) 名為prototype的公有并且不可枚舉的屬性店雅,它會(huì)指向另一個(gè)對(duì)象政基,這個(gè)對(duì)象通常被稱為該對(duì)象的原型。

function Foo() {
 // ...
}
Foo.prototype; // { }

在方法射調(diào)用new時(shí)創(chuàng)建對(duì)象時(shí)闹啦,該對(duì)象最后會(huì)被關(guān)聯(lián)到這個(gè)方法的prototype對(duì)象上沮明。

function Foo() { 
  // ...
}
var a = new Foo();
Object.getPrototypeOf( a ) === Foo.prototype; // true

new Foo()會(huì)生成一個(gè)新對(duì)象,這個(gè)新對(duì)象的內(nèi)部鏈接[[Prototype]]關(guān)聯(lián)的是 Foo.prototype對(duì)象亥揖。最后我們得到了兩個(gè)對(duì)象珊擂,它們之間互相關(guān)聯(lián)。

JavaScript中费变,我們并不會(huì)將一個(gè)對(duì)象(“類(lèi)”)復(fù)制到另一個(gè)對(duì)象(“實(shí)例”)摧扇,只是將它們關(guān)聯(lián)起來(lái)。這個(gè)機(jī)制通常被稱為原型繼承挚歧。

構(gòu)造函數(shù)

使用new創(chuàng)建的對(duì)象會(huì)調(diào)用類(lèi)的構(gòu)造函數(shù)扛稽。

function Foo() { 
  // ...
}
Foo.prototype.constructor === Foo; // true
var a = new Foo();
a.constructor === Foo; // true

Foo.prototype默認(rèn)有一個(gè)公有并且不可枚舉的屬性.constructor,這個(gè)屬性引用的是對(duì)象關(guān)聯(lián)的函數(shù)滑负。

可以看到通過(guò)“構(gòu)造函數(shù)”調(diào)用new Foo()創(chuàng)建的對(duì)象也有一個(gè).constructor屬性在张,指向 “創(chuàng)建這個(gè)對(duì)象的函數(shù)”。

函數(shù)本身并不是構(gòu)造函數(shù)矮慕,然而帮匾,當(dāng)你在普通的函數(shù)調(diào)用前面加上new關(guān)鍵字之后,就會(huì)把這個(gè)函數(shù)調(diào)用變成一個(gè)“構(gòu)造函數(shù) 調(diào)用”痴鳄。實(shí)際上瘟斜,new會(huì)劫持所有普通函數(shù)并用構(gòu)造對(duì)象的形式來(lái)調(diào)用它。

JavaScript中對(duì)于“構(gòu)造函數(shù)”最準(zhǔn)確的解釋是痪寻,所有帶new的函數(shù)調(diào)用螺句。

如果 你創(chuàng)建了一個(gè)新對(duì)象并替換了函數(shù)默認(rèn)的.prototype對(duì)象引用,那么新對(duì)象并不會(huì)自動(dòng)獲 得.constructor屬性橡类。

function Foo() { /* .. */ }
Foo.prototype = { /* .. */ }; // 創(chuàng)建一個(gè)新原型對(duì)象
var a1 = new Foo();
a1.constructor === Foo; // false! 
a1.constructor === Object; // true!

可以給 Foo.prototype 添加一個(gè) .constructor 屬性蛇尚,不過(guò)這需要手動(dòng)添加一個(gè)符
合正常行為的不可枚舉屬性。

function Foo() { /* .. */ }
Foo.prototype = { /* .. */ }; // 創(chuàng)建一個(gè)新原型對(duì)象

Object.defineProperty( Foo.prototype, "constructor" , {
    enumerable: false,
    writable: true,
    configurable: true,
    value: Foo // 讓 .constructor 指向 Foo
});

繼承

典型的“原型風(fēng)格”:

function Foo(name) { 
  this.name = name;
}
Foo.prototype.myName = function() { 
  return this.name;
};
function Bar(name,label) { 
  Foo.call( this, name ); 
  this.label = label;
}

// 我們創(chuàng)建了一個(gè)新的 Bar.prototype 對(duì)象并關(guān)聯(lián)到 Foo.prototype
// 注意!現(xiàn)在沒(méi)有 Bar.prototype.constructor 了 
// 如果你需要這個(gè)屬性的話可能需要手動(dòng)修復(fù)一下它
Bar.prototype = Object.create( Foo.prototype );
Bar.prototype.myLabel = function() { 
  return this.label;
};
var a = new Bar( "a", "obj a" );
a.myName(); // "a"
a.myLabel(); // "obj a"

ES6 開(kāi)始可以直接修改現(xiàn)有的Bar.prototype

Object.setPrototypeOf( Bar.prototype, Foo.prototype );

檢查一個(gè)實(shí)例的繼承關(guān)系

// 非常簡(jiǎn)單:b 是否出現(xiàn)在 c 的 [[Prototype]] 鏈中
b.isPrototypeOf( c );

Object.getPrototypeOf( a ) === Foo.prototype; // true

// 非標(biāo)準(zhǔn)的方法訪問(wèn)內(nèi)部 [[Prototype]] 屬性
 a.__proto__ === Foo.prototype; // true

寫(xiě)了這么多顾画,實(shí)在寫(xiě)不下去了取劫〈殷裕《你不知道的js》都是滿滿的干貨,筆記記到這里發(fā)現(xiàn)好多知識(shí)都非常有用勇凭,沒(méi)辦法省略疚膊。幾下這些筆記,也是為了復(fù)習(xí)一下虾标,以免忘得太快了寓盗,所以受益的終究還是自己呀。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末璧函,一起剝皮案震驚了整個(gè)濱河市傀蚌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蘸吓,老刑警劉巖善炫,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異库继,居然都是意外死亡箩艺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)宪萄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)艺谆,“玉大人,你說(shuō)我怎么就攤上這事拜英【蔡溃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵居凶,是天一觀的道長(zhǎng)虫给。 經(jīng)常有香客問(wèn)我,道長(zhǎng)侠碧,這世上最難降的妖魔是什么抹估? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮弄兜,結(jié)果婚禮上棋蚌,老公的妹妹穿的比我還像新娘。我一直安慰自己挨队,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蒿往。 她就那樣靜靜地躺著盛垦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瓤漏。 梳的紋絲不亂的頭發(fā)上腾夯,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天颊埃,我揣著相機(jī)與錄音,去河邊找鬼蝶俱。 笑死班利,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的榨呆。 我是一名探鬼主播罗标,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼积蜻!你這毒婦竟也來(lái)了闯割?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤竿拆,失蹤者是張志新(化名)和其女友劉穎宙拉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體丙笋,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谢澈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了御板。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锥忿。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖稳吮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灶似,我是刑警寧澤列林,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站酪惭,受9級(jí)特大地震影響希痴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜春感,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一砌创、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲫懒,春花似錦嫩实、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至颂翼,卻和暖如春晃洒,著一層夾襖步出監(jiān)牢的瞬間慨灭,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工球及, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留氧骤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓吃引,卻偏偏與公主長(zhǎng)得像筹陵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子际歼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容