this有四種情況!
-
當在函數調用的時候指向widow
-
當方法調用的時候指向調用對象
-
當用apply和call上下文調用的時候指向傳入的第一個參數
-
構造函數調用指向實例對象
函數裏的this可以分爲兩種來記憶:
如果是使用new方式創建對象,this指向新建的那個對象;
如果只是普通的調用,誰調用這個函數,函數裏的this就指向誰~
apply
可以改變this
的指向,接收兩個參數,第一個參數是在其中運行函數的作用域,另外一個是參數數組
var name = "xh";
var age = 22;
function print(name, age) {
console.log('this指向的值', this);
console.log(this.name, this.age);
console.log('傳過來的值', name, age);
}
let obj = {
name: 'xm',
age: '21',
print: function () {
console.log('this指向的值', this);
console.log(this.name, this.age);
}
};
print.apply(this, ['xd', 20]);
console.log("================");
print.apply(window, ['xd', 20]);
console.log("================");
print.apply(obj, ['xd', 20]);
console.log("================");
print.apply(obj);
console.log("================");
print.apply();
console.log("================");
obj.print.apply();
如果apply不帶任何參數,默認指向windows
call
call
和apply
一樣,可以改變this
的指向,只是參數傳遞的方式不一樣,第一個參數是在其中運行函數的作用域,其他的參數與函數的參數一一對應,和apply
不一樣,apply
的第二個參數是一個數組,call
的參數必須一個一個的傳入進去
var name = "xh";
var age = 22;
function print(name, age) {
console.log('this指向的值', this);
console.log(this.name, this.age);
console.log('傳過來的值', name, age);
}
let obj = {
name: 'xm',
age: '21',
print: function () {
console.log('this指向的值', this);
console.log(this.name, this.age);
}
};
print.call(this, 'xd', 20);
console.log("================");
print.call(window, 'xd', 20);
console.log("================");
print.call(obj, 'xd', 20);
console.log("================");
print.call(obj);
console.log("================");
print.call();
console.log("================");
obj.print.call();
call
和apply
一樣,如果沒有參數,默認指向的是windows
bind
bind
也可以改變函數的this指向,可以綁定this
的函數的作用域
var name = "xh";
var age = 22;
function print(name, age) {
console.log('this指向的值', this);
console.log(this.name, this.age);
console.log('傳過來的值', name, age);
}
let obj = {
name: 'xm',
age: '21',
print: function () {
console.log('this指向的值', this);
console.log(this.name, this.age);
}
};
let print1 = print.bind(window);
print1();
console.log("==============");
let print2 = print.bind(obj);
print2();
console.log("==============");
let print3 = print.bind();
print3();
console.log("==============");
let print4 = obj.print.bind();
print4();
bind
在沒有參數的情況下,默認綁定的是windows
面試題
var name = "The window";
let object = {
name: "my Object name",
getNameFun: function () {
return function () {
return this.name;
};
}
};
console.log(object.getNameFun()()); //The window
//可拆解爲
// var result = object.getNameFun();
// result(); //等價與window.result();
//所以object裏面的this是windows
//使用var定義變量,定義的是全局變量,即var name = "The window"等價與windows.name = "The window"
let name1 = "The window 1";
let object1 = {
name: "my Object name 1",
getNameFun: function () {
return function () {
return this.name1;
};
}
};
console.log(object1.getNameFun()()); //undefined
//可拆解爲
// var result = object.getNameFun();
// result(); //等價與window.result();
//所以object裏面的this是windows
//使用let定義變量,定義的是局部變量,即let name = "The window 1"並不會在windows變量上添加一個name屬性
//所以輸出爲undefined
var name2 = "The window2";
let object2 = {
name2: "my Object name 2",
getNameFun: function () {
let that = this;
return function () {
return that.name2;
}
}
};
console.log(object2.getNameFun()()); //my Object name 2
//可拆解爲
var result = object.getNameFun();
//result裏面有個閉包,閉包的that屬性指向object
result(); //等價與window.result();