學(xué)了多種語(yǔ)言狼忱,發(fā)現(xiàn)
javascript
的this
是最難以捉摸的摊崭。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.a
和obj.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"
bar
是obj.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
綁定
JavaScript
中new
的機(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í)行下面的操作。
創(chuàng)建(或者說(shuō)構(gòu)造)一個(gè)全新的對(duì)象胧卤。
這個(gè)新對(duì)象會(huì)被執(zhí)行[[原型]]連接唯绍。
這個(gè)新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this。
如果函數(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
蛾魄、Function
和RegExp
來(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:false
和configurable: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í)一下虾标,以免忘得太快了寓盗,所以受益的終究還是自己呀。