《你不知道的JavaScript上卷》第二部分第1章-第2章
1.是指向自身嗎钮呀?
var a = 1
function foo() {
console.log("this.a=", this.a)
}
foo.a = 2;
foo();
console.log("foo.a=", foo.a);
console.log("foo instanceof Object", foo instanceof Object)
// 結(jié)果:
// 瀏覽器環(huán)境下:this.a= 1 foo.a= 2
// node環(huán)境下this.a= undefined foo.a= 2
我們都知道在JavaScript中Function也是Object,foo instanceof Object的值為true姻檀,所以我們可以給函數(shù)foo添加一個(gè)屬性a,a的值為2涝滴。如果this指向自身的話绣版,foo中this.a的值應(yīng)該是2才對(duì),由此可見this并不指向自身歼疮。
PS:node環(huán)境var聲明并不會(huì)添加到global中杂抽。
2.是指向函數(shù)所在的作用域嗎?
var a = 1;
function foo() {
var a = 2;
function bar() {
console.log("this.a=", this.a);
}
bar();
}
foo();
// 結(jié)果:this.a= 1
從第一段代碼我們知道this并不指向自身韩脏,第二段代碼中我們?cè)趂oo函數(shù)的作用域內(nèi)聲明了一個(gè)變量a=2和一個(gè)函數(shù)bar缩麸,并在當(dāng)前作用域內(nèi)執(zhí)行了bar,如果this指向當(dāng)前作用域的話赡矢,bar函數(shù)中this.a的值應(yīng)該是2才對(duì)杭朱,由此可見this也并不指向函數(shù)所在作用域。
結(jié)論:this既不指向自身吹散,也不指向所在作用域弧械,實(shí)際上this是在運(yùn)行時(shí)進(jìn)行綁定的,而不是在編寫的時(shí)候綁定空民。this是在函數(shù)發(fā)生調(diào)用時(shí)發(fā)生的綁定它指向什么完全取決于函數(shù)在哪里被調(diào)用
3.綁定規(guī)則:
1.默認(rèn)綁定
function foo() {
console.log("this.a=", this.a);
}
var a = 2;
foo();
//結(jié)果:this.a=2
function foo() {
'use strict'
console.log("this.a=", this.a);
}
var a = 2;
foo();
// 結(jié)果:TypeError: Cannot read property 'a' of undefined
非嚴(yán)格模式下this綁定到window上梦谜,嚴(yán)格模式會(huì)綁定到undefined
2.隱式綁定
var a = 2;
function foo() {
console.log("this.a=", this.a);
}
var obj = {
a: 3,
foo: foo
}
obj.foo();
//結(jié)果:this.a= 3
對(duì)象屬性引用鏈中只有上一層或者說(shuō)最后一層在調(diào)用位置起作用;
var a = 2;
function foo() {
console.log("this.a=", this.a);
}
var obj1 = {
a: 3,
foo: foo
}
var obj2 = {
a: 4,
obj1: obj1
}
obj2.obj1.foo();
//結(jié)果:this.a= 3
3.顯示綁定
常用的綁定方法bind(...),call(...)和apply(...),
var a = 2;
function foo() {
console.log("this.a=", this.a);
}
var obj = {
a: 3
}
foo.call(obj);
foo.apply(obj);
var bar = foo.bind(obj);
bar();
//結(jié)果:打印三遍 this.a= 3
4.new綁定
使用new來(lái)調(diào)用函數(shù)時(shí)會(huì)自動(dòng)執(zhí)行以下操作
創(chuàng)建一個(gè)全新對(duì)象袭景;
這個(gè)對(duì)象會(huì)被執(zhí)行[[Prototype]]連接;
這個(gè)新對(duì)象會(huì)被綁定到函數(shù)調(diào)用的this闭树;
-
如果函數(shù)沒有返回其他對(duì)象耸棒,那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對(duì)象;
var a = 2; function foo(a) { this.a = a; } var bar = new foo(3); console.log("this.a=",bar.a) //結(jié)果:this.a= 3
優(yōu)先級(jí)問題
new綁定>顯示綁定>隱式綁定>默認(rèn)綁定
小結(jié):
- 由new調(diào)用綁定到新創(chuàng)建的對(duì)象上报辱;
- 由bind,call,apply調(diào)用綁定到指定對(duì)象上与殃;
- 由上下文對(duì)象調(diào)用綁定到這個(gè)上下文對(duì)象上;
- 默認(rèn):在嚴(yán)格模式上綁定到undefined碍现,否則綁定到全局對(duì)象上幅疼;
- 箭頭函數(shù)并不會(huì)使用以上規(guī)則,而是根據(jù)當(dāng)前詞法作用域來(lái)決定this昼接,箭頭函數(shù)會(huì)繼承外層函數(shù)調(diào)用的this綁定(無(wú)論this綁定到什么)爽篷。 其實(shí)和ES6之前代碼中的self = this機(jī)制一樣;