1.this的作用
function identify() {
return this.name.toUpperCase();
}
function sayHello() {
var greeting = "Hello, I'm " + identify.call( this );
console.log( greeting );
}
var person1= {
name: "Kyle"
};
var person2= {
name: "Reader"
};
identify.call( person1); // KYLE
identify.call( person2); // READER
sayHello.call( person1); // Hello, I'm KYLE
sayHello.call( person2); // Hello, I'm READER
用來綁定對象,進行屬性和方法的操作。
順便說一句:
JS中不在乎你寫成什么,而在于你把它看成什么。
個人認為:萬物皆為對象。對象內部存在屬性和方法。
2.只有4種方式改變this指向
2.1 默認綁定全局變量
這條規則是最常見的,也是默認的。當函數被單獨定義和調用的時候,應用的規則就是綁定全局變量。如下:
function fn() {
console.log( this.a );
}
var a = 2;
fn(); // 2 -- fn單獨調用,this引用window
2.2 隱式綁定
隱式調用的意思是,函數調用時擁有一個上下文對象,就好像這個函數是屬于該對象的一樣。
這里需要了解,函數內部的this指向調用該函數的對象。
例如:
function fn() {
console.log( this.a );
}
var obj = {
a: 2,
fn: fn
};
obj.fn(); // 2 -- this引用obj。
需要說明的一點是,最后一個調用該函數的對象是傳到函數的上下文對象
function fn() {
console.log( this.a );
}
var obj2 = {
a: 42,
fn: fn
};
var obj1 = {
a: 2,
obj2: obj2
};
obj1.obj2.fn(); // 42 -- this引用的是obj2.
還有一點要說明的是,失去隱式綁定的情況,如下:
function fn() {
console.log( this.a );
}
var obj = {
a: 2,
fn: fn
};
var bar = obj.fn; // 函數引用傳遞
var a = "全局"; // 定義全局變量
bar(); // "全局"
如上,第8行雖然有隱式綁定,但是它執行的效果明顯是把fn賦給bar。這樣bar執行的時候,依然是默認綁定全局變量,所以輸出結果如上。
2.3 顯示綁定
學過bind()\apply()\call()函數的都應該知道,它接收的第一個參數即是上下文對象并將其賦給this。看下面的例子:
function fn() {
console.log( this.a );
}
var obj = {
a: 2
};
fn.call( obj ); // 2
如果我們傳遞第一個值為簡單值,那么后臺會自動轉換為對應的封裝對象。如果傳遞為null,那么結果就是在綁定默認全局變量,如:
function fn() {
console.log( this.a );
}
var obj = {
a: 2
};
var a = 10;
fn.call( null); // 10
其中call和apply作用相同,但是apply后面接偽數組[1,2,3],call后面接正規參數(a,b,c)或者數組[1,2,3]。
而bind在ES5中提出,用來解決apply和call沒有解決的問題。將方法執行和this綁定分開。
2.4 new新對象綁定
如果是一個構造函數,那么用new來調用,那么綁定的將是新創建的對象。如:
function fn(a) {
this.a = a;
}
var bar = new fn( 2 );
console.log( bar.a );// 2
其實第四條和第三條是同樣的。new的過程中,自動發生了call方法,進行了this的綁定。