先直接上题:
let length = 10;
function fn(){
return this.length+1
}
let obj = {
length:5,
test1:function(){
return fn()
}
}
obj.test2=fn;
console.log(obj.test1())//1 此处,this的指向的是window,window.length返回当前窗口中frames的数量(包括IFRAMES)
console.log(fn()===obj.test2())//false,其中fn()返回1,obj.test2()返回6
如果你的答案回答正确了,那么恭喜你,说明你已经掌握JS中函数的this指向了;如果没回答正确,请不要灰心,说明你还需要再仔细研究一下。
this指向特殊注意:
说到this的指向:首先要说明的是this在函数的定义的时候是不能确定的(除箭头函数之外),只有在函数执行的时候才能确定this的执行,在大多数情况下,this最终指向的是那个最后调用它的对象(除特殊情况外)。
this的绑定规则有:new绑定,硬绑定(call,apply,bind),隐式绑定,默认绑定规则;这些规则都有很多文章详细说明;我这里着重强调以下几点:
- 对象的方法是由箭头函数声明的,此时,若无特殊情况,对象调用该方法执行时,this的指向是window(非严格模式下);
var a=1;
const obj ={
a:4,
print:()=>{console.log(this.a)}
}
obj.print();//1
var a= 5;
const obj = {
a:6,
print:()=>{console.log(this.a)}
}
obj.print.call({a:7})//5
2.对象的方法中含有嵌套函数的时候,此时,若无特殊情况,对象调用该方法执行时,this指向的是window(非严格模式下)
var name = "window.name";
var obj = {
name : "obj.name",
getName:function(){
console.log(this.name);
return function(){
console.log(this.name);
}
}
}
obj.getName()(); // "obj.name" "window.name"
题解:
开篇的那段代码特别的巧妙,因为它使用的是let,并不是全局声明了一个length变量;如果稍不注意,一时忽略了函数的length属性,或者window的length属性;这道题很有可能进入出题这的陷阱;
- 需要明白函数的length属性指的是形参的个数,是指必须要传多少个参数;并且注意⚠️形参的个数不包括剩余参数的个数,仅包括第一个具有默认值之前的参数个数。
- window的length属性是指当前窗口包含的框架的数量; 因此,上题中单独执行fn()时,this的指向为window,无其他框架下,返回的是1;而Obj.test2(),this的指向是obj,因此返回的是6;而由于obj中的test1方法中是嵌套函数,因此在嵌套函数中的this指向的是window,因此,执行obj.test1()时,返回的也是1.