Skip to main content

this指针

求以下代码的输出结果

var length = 10;
var obj1 = {
length: 6,
method: function () {
console.log(this.length)
}
}

var obj2 = {
length: 3,
method: function (fn) {
fn();
arguments[0]();
}
}

obj2.method(obj1.method, obj2.method); // 求打印输出结果

题解之前先总结一下js中的this总共有哪几种场景,以及各类场景中this的指向

  1. 方法调用:this的值就是在点符号 . (或者方括号 []) 之前的那个对象!!
  2. 函数调用: this指向window, 严格模式下,如果this没有被执行环境,那么this就是undefined
  3. 构造函数调用: this指向被构造的对象
  4. apply, call, bind:this指向第一个参数
  5. 箭头函数:箭头函数中的this在箭头函数被定义的地方就绑死了!! 不是执行的时候才确定的

其实这里重点需要注意的就是第一条和最后一条,在比较混乱的调用关系中务必记得,找到函数调用时 .符号前面的那个对象,它,就是this所指! 箭头函数声明的时候就可以分析出它this的指向,按着作用域链向上查找,如果箭头函数被普通函数包裹,那么箭头函数的this就是外面包裹它的普通函数的this, 如果没有函数包裹箭头函数,则它的this指向外层全局对象。

tip

普通JS函数中的this值,是在函数真正执行的时候 动态求值 的 其值取决于最终调用它的那个对象;箭头函数中的this指向,在箭头函数定义被声明的时候就绑定好了, 在分析this指向的题目时候遇到普通函数的this可以继续往下读不必立刻分析其指向,遇到箭头函数可以先停下来确定其this指向,做好标记再继续读下面的代码。

// 热身小练习

let name = 'global';
let demo = {
name: 'xiaoyu',
sayName: () => console.log(this.name),
sayMyName: function () {
console.log(this.name)
}
}

demo.sayName(); // 输出啥??
demo.sayMyName(); // 输出啥??
// 题解

var length = 10; // 全局变量 length: 10

var obj1 = {
length: 6,
method: function () {
console.log(this.length); // 非箭头函数,其内部的this,要看是谁调用的
}
}

var obj2 = {
length: 3,
method: function (fn) {
fn();
arguments[0](); // arguments 是一个类数组的 **对象!!** 它是个对象,记住后面要考!
}
}

// 分析: 执行 obj2.method(arg1, arg2) 函数调用,第一个参数是一个回调函数其值为obj1.method,
// 然后函数体内执行了 fn(), 我们找 fn()前面的点 . 有么?? 没有! 这里是一个全局的函数调用,
// 所以其里面的this 指向的是 全局对象,故第一个输出是 10;
// 继续看 arguments[0]() 这句看着很奇怪的代码调用,前面我们说 arguments 是一个类数组对象,它不是一个
// 严格意义上的数组,它有 length 属性,并且 它的属性访下标从0开始,但是它没有Array的其他方法。
// 坑就在这里,arguments 说到底它是一个有 length 属性的 对象!然后我们在看 arguments[0]() 这行调用
// arguments[0] 定位到了传递进来的第一个函数也即fn, 然后arguments[0]()直接执行了该函数,这里就是一个
// 隐藏的很深的,普通函数在对象中以 . 或者 [] 调用的方式,其内部的this 指向 . 或者 [] 前面的对象,在这里
// 就是 arguments 对象,所以 this.length 最后是 2 ,因为我们实际是传递了两个参数 ,你答对了么!
obj2.method(obj1.method, obj2.method);
// 热身小练习 题解
let name = 'global';
let demo = {
name: 'xiaoyu',
sayName: () => console.log(this.name),
sayMyName: function () {
console.log(this.name)
}
}

demo.sayName(); // 输出 global
demo.sayMyName(); // 输出 xiaoyu

// 你答对了么 🫥