this指向可以理解为把this跟他要指向的东西绑定起来,也就是说 this有四种绑定方式默认绑定,隐式绑定,显式绑定,new绑定.
默认绑定
其实就是函数调用,绑定全局对象window,如果是严格模式,这个时候绑定的为undefined.(打脸第一个不详细的)
new绑定
通过new调用的函数,那么this绑定的是new出来的新对象,前提是构造函数没有返回一个对象或者function,否则this绑定的是返回的对象或者函数
隐式绑定
函数被对象通过点语法调用的,一般是obj.fn(),这时候this指向的是这个对象
显式绑定
也可以叫做硬绑定,还记得,call,apply,bind; 硬绑定,就是硬生生的改过来!!!
补充一下: 这三个方法,又叫方法借用模式,简单讲,就是某个对象想用一个方法,但是自己没有,于是就找个人借一下. 举个例子
var wsz = {
0: "xh",
1: "xb",
2: "xl",
length: 3
};
//有上面这个对象,现在的需求是将lw这个元素添加到上面这个对象里,并且同时改变length的值
首先,这是一个伪数组,需求可以知道是让我们把"3:lw"加进去,传统的方法?
wsz[3] = "lw";
wsz.length = 4;
console.log(wsz)
打印结果:

显然可以实现需求,那么如果需求是让我们加上七八十个呢?显然这样做就会累死得咯,想下班儿?加班儿还不是自己作出来的 思考:既然是一个伪数组,那么,伪数组和数组的区别?长的差不多,但是不能用数组的方法,可是好像数组有个push方法很合适这个需求,能否借来用用?
那么,我们可以尝试一下
Array.prototype.push.call(wsz,"lw"); //push方法在哪儿就去哪儿借呗
运行结果

如果要依次加很多,就用apply方法,第二个参数传一个数组或者为数组就好了
Array.prototype.push.apply(wsz,wsz); //push方法在哪儿就去哪儿借呗
方法借用的思路: 1.想清楚借啥方法 2.想清楚找谁借 3.请call或者apply去帮你借
注意的是,我们用硬绑定的时候,简单说的是想给谁绑定就写谁,但是,如果传入的是null或者undefined,这些值在绑定的时候会被忽略,结果依然是默认绑定的,返回的是window或者undefined(严格模式下)
检验一下掌握结果吧:
var number = 5;
var obj = {
number: 3,
fn1: (function () {
var number;
this.number *= 2;
number = number * 2;
number = 3;
return function () {
var num = this.number;
this.number *= 2;
console.log(num);
number *= 3;
console.log(number);
}
})()
}
var fn1 = obj.fn1;
fn1.call(null);
obj.fn1()
console.log(window.number);
//分析一下
//自执行函数在书写完成时就已经执行了 做的事情是:
// 1.给自己声明一个number对象
// 2.由于是自执行函数,this指向全局window,因此第二句代码将全局number变为10
// 3.给自己声明的number赋值为3
// 4.把那个函数返回出来
// 之后所有的调用全都是调用的返回值函数
//每一句的作用:
//第一次调用:
var fn1=obj.fn1; //将返回值函数赋给fn1
fn1.call(null); // call方法调用,看似是硬绑定,由于传参为null,因此相当于默认绑定,this指向window相当于window调用那个返回值函数 然后看函数内部代码
var num = this.number; //声明一个num变量,将this(全局)的number赋给num,此时 num=10
this.number*=2 //将全局的number变为20
console.log(num) //第一次打印为 10
number*=3 //按照变量搜索原则,找到自执行函数里的number并且变为了9
console.log(number) //第二次打印自执行函数里的number 9
//第二次调用:
obj.fn1() //对象调用,隐式绑定,返回值函数里的this指向obj,相当于obj再次调用自执行函数返回的那个函数 然后看函数内部
var num = this.number; //重新声明一个num变量,将this(obj)的number赋给num,此时 num=3
this.number*=2 //注意this指向的是obj 因此将obj的number变成6
console.log(num) //第三次打印 3
number*=3 //按照变量搜索原则,找到自执行函数里的number 此时经过第一次调用 number已经为9 因此将它变为27
console.log(number) //第四次打印自执行函数的number 27
console.log(window.number); //最后一次打印的是全局的number 20
所以最后结果为

需要注意的是
箭头函数的this指向的是外部的this,所以在使用定时器的时候,参数function常用箭头函数处理this指向问题.
参考
刘小夕 【面试篇】寒冬求职季之你必须要懂的原生JS(上)
juejin.cn/post/684490…
更新一波面试题
分享刚遇到的一个面试题
var obj = {
foo: 'bar',
func: function () {
var self = this
console.log('outer func: self.foo = ' + self.foo)
console.log('outer func: this.foo = ' + this.foo)
(function () {
console.log('inner func : self.foo = ' + self.foo)
console.log('inner func : this.foo = ' + this.foo)
}())
}
}
obj.func()
单看调用方式,obj.func() ,显然这叫隐式绑定,此时函数内部的this指向obj,不管换不换名字,所以,self和this都指向obj,因此,前两个输出都是bar
之后为一个自调用函数,他的this指向的是window,但是self还是外部被对象调用的函数的self(this),因此第三个输出还是bar
第四个输出因为this已经指向全局window,因此打印的是undefined
可恶,居然紧张的这种题都能错,完辽.