【js基础】几道this题
第一道
function test() {
console.log(this.name);
}
var obj = {
name: 'whoami',
getName: test
};
var name = 'which';
obj.getName();
var output = obj.getName;
output();
我的答案:'whoami', 'which'
对 (在严格模式下,答案为'whoami', undefined)
第二道
function test() {
console.log(this.name);
}
var obj = {
name:'whoami',
getName: test
};
setTimeout(obj.getName,1000);
我的答案:'whoami'
错。答案为undefined
第三道
function test(x){
this.x = x;
return this;
}
var x = test(5);
var y = test(6);
console.log(x.x);
console.log(y.x);
我的答案: undefined, undefined
对,错。答案为undefined,6
解答:
第一道题涉及的知识点:this绑定的两种方式以及绑定丢失
第二道题…:this隐式绑定、绑定丢失
第三道题…:this默认绑定、变量提升、同名变量知识
在彻底明白上面结果是如何得来前,先具体讲解下this的绑定时间、四种绑定方式以及其优先级:
this存在于所有函数中,在函数调用时被赋值
1.默认绑定
此时this的指向是window对象(非严格模式下,严格模式下 默认绑定this === undefined)
function test() {
console.log(this);
}
test(); // this === window
2.隐式绑定
此时this指向包含它的对象
function test(){
console.log(this);
}
var obj = {
getValue: test
};
obj.getValue(); // obj {}
3.显式绑定
就是使用call、apply或bind方法来显式绑定
function test() {
console.log(this);
}
var obj = {
name: 'whoami'
};
test.call(obj); // obj {name: 'whoami'}
4.new绑定
就是使用new关键字会存在this的绑定
functionTest() {
console.log(this);
}
var test = new Test(); // Test(){}
这四种方式的优先级如下(从高到低依次):
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定
绑定丢失
凡事总有例外,this的绑定也是,下面说明几种例外:
1、赋值带来的绑定丢失
function test() {
console.log(this);
}
var obj = {
getValue: test // 此处是隐式绑定
};
var output = obj.getValue; // 赋值
output(); // 赋值导致绑定丢失,此时应用默认绑定
/**
* (output = obj.getValue)() 等价于output()
*/
/**
* setTimeout() 实际上类似于
* function setTimeout(fn, delay) {
* }
* fn = obj.getValue故也会导致绑定丢失,应用默认绑定
*/
setTimeout(obj.getValue, 1000);
2、null或undefined带来的绑定丢失
function test() {
console.log(this);
}
test.call(null); // this === undefined(严格模式下)
test.call(undefined); // this === window(非严格模式下)
test.call(2); // 此时应用显式绑定,因为除了Null、Undefined类型之外的其他类型在进行操作时都会在底层产生该类型的对象
再回头看三道面试题:
第一道是隐式绑定,不过存在赋值导致绑定丢失,应用默认绑定
第二道同样如此
第三道是默认绑定,不过主要考察点在于变量提升以及同名变量的处理
就具体分析下第三道面试题:
function test(x) {
this.x = x;
return this;
}
var x = test(5);
var y = test(6);
console.log(x.x);
console.log(y.x);
因为全局变量会自动成为window的属性、变量和函数提升的问题,上面的代码实际上如下:
function test(x) {
// this === window,所以this.x = window.x
this.x = x;
return this;
}
var x, y;
x = test(5);
// 此时window.x === x, x === widnow
y = a(6);
// 此时x === 6
// x.x 此时为6.x, 故为undefined
console.log(x.x);
// y.x 此时为window.x
console.log(y.x);
下面补充下其他情况this指向:
函数内部函数中this指向的问题,在内部函数中this使用默认绑定
function test() {
(function() {
console.log(this);
})();
}
test(); // this === window
ES6中增加了箭头函数,该函数有两个作用:
简写函数定义
this指向明确,指向该函数所在作用域的this的值
实例:
var test = () => console.log(this);
test(); // this === window
test.call({}); // this === window