你真的懂this指向吗?

156 阅读2分钟

先直接上题:

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),隐式绑定,默认绑定规则;这些规则都有很多文章详细说明;我这里着重强调以下几点:

  1. 对象的方法是由箭头函数声明的,此时,若无特殊情况,对象调用该方法执行时,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属性;这道题很有可能进入出题这的陷阱;

  1. 需要明白函数的length属性指的是形参的个数,是指必须要传多少个参数;并且注意⚠️形参的个数不包括剩余参数的个数,仅包括第一个具有默认值之前的参数个数。
  2. window的length属性是指当前窗口包含的框架的数量; 因此,上题中单独执行fn()时,this的指向为window,无其他框架下,返回的是1;而Obj.test2(),this的指向是obj,因此返回的是6;而由于obj中的test1方法中是嵌套函数,因此在嵌套函数中的this指向的是window,因此,执行obj.test1()时,返回的也是1.