面试官问的this指向问题你都能答对吗

257 阅读2分钟

话不多说先看题

const name ='a'
const obj={
    name:'b',
    getName(){
        return this.name;
    },
    prop:{
        name:'c',
        getName:()=>{
            return this.name
        }
    }
}
console.log(obj.getName())
console.log(obj.getName.call(obj.prop))
console.log(obj.prop.getName())

this 是很多⼈会混淆的概念,但是其实他⼀点都不难,你只需要记住⼏个规则就可以了。

  • 第一种情况是this只依赖于调⽤函数前的对象,前面无对象就依赖全局window对象
  • 第二种情况是利⽤ call,apply,bind 改变 this。
  • 第三种情况是箭头函数 中的 this。 箭头函数其实是没有 this 的,这个函数中的 this 只取决于他外⾯的第⼀个不是箭头函数 的函数的 this 。 所以现在知道答案了吧,答案在文章底部。

call、apply、bind是如何改变this的
  • call、apply、bind三个方法都有两个参数;第一个参数都是this(对象),即被改变后的this指向。
  • call和apply都是立即执行函数,不必调用。call第二个参数不用数组接收,apply用数组接收,类型可以是任意类型
  • bind返回值是一个函数(不会立即执行,需要调用),传参和call一样
  • 一个函数.call() 2次或者2次以上 执行的永远是第一个参数(第一个参数需要是一个函数),参数会直接输出

下面来做一些题看看自己有没有真的理解吧。

function a(b){
    console.log('执行了a' + this.b1 + b)
}
let b={b1:"b1"};
a.call(b,"第二个参数");
function a(){ console.log(this + '执行了a')};

function b(){console.log(this + "执行了b")}
a.call(b)
a.call.call(b)
我们都知道js的数组处理方法很多,可以很方便的对数据进行增删改截取添加的处理,
所以我们可以利用call将传入具有length属性的参数转为数组.
例如:
let str = 'string'
Array.prototype.slice.call(str, 2)
使用call冒充一个据有length对象,转换成数组,绑定this指向——>对象.slice() 或者  字符.slice() 或者  数组.slice() ——>第二个参数为截取的起始下标

答案是:b c undefined

补充一个知识点: let和const声明的变量不在window上。 ES6规定var命令与function命令声明的全局变量,依旧是顶层对象的属性,但let命令,const命令、 class命令声明的全局变量,不属于顶层的属性。不用对象去取用,在块级作用域中即可取用.