本章解决问题: 1. this是什么,为何引入? 2. 关于this的误解 3. this绑定规则和判定 4. 箭头函数的this绑定
1、this是什么,为何引入?
答:
- 本质:this是JS中的一个关键字;
- 作用:this的作用是通过指向来传递对象的引用;
- 为何引入:为了更优雅的传递对象的使用;
- 如何使用:只有函数才有this相关概念,this的指向完全取决函数的调用方式;
- 注意点:
1)this是在运行时绑定的,而非编写时;
2)this的绑定只与函数调用方式有关,与申明无任何关系;
2、目前关于this指向有何误解?
答:
- this并不是指向函数的调用者:
-也就是说this并不是单纯的指向它的调用者,而是依靠一定的绑定规则进行优先级的比较,最终决定this的绑定; - this并不指向函数本身: (以下面的一个例子为例)
-如果this指向的是fn,那么最终的cnt应该是2,但结果确是0;
-实际这里的this绑定的是widows对象,所以没改变fn的count;
function fn () {
this.count ++ ;
}
fn.count = 0;
for(let i = 0;i<5;i++){
if(i > 2) {
fn(i);
}
}
console.log(fn,count); // 0
3、this绑定规则
答:
1)默认绑定:当前执行函数没有调用它的对象时,this指向全局对象,在浏览器中就是Window对象(非strict) 注意:必须是对象调用函数!如果函数调用函数,等同于没调用;
代码0中:函数调用带this函数,this永远指向Window全局;
2)隐式绑定:当函数前面有调用它的对象时,this指向调用函数最近的对象
2.1)隐式绑定的丢失
在特殊情况下隐式绑定会丢失,最常见的两种:作为参数传递和最为变量赋值; 丢失后的绑定规则: 若作为函数参数传递丢失,this直接指向Window全局对象(非严),与函数this无关; 若变量赋值后丢失,this重新寄托在新变量上; - 代码1中:作为参数传递丢失,重新定位在fn1上,所以this指向Window; - 代码2中:变量赋值丢失,重新定位在fn上; - 代码3中:带this的函数作为setTimeout的参数传递,this指向Window对象;
3)显式绑定
就是使用call()apply()和bind()方法手动的改变this的指向; - 代码4中:自己改变this的指向并调用函数; - 注意: 若第一个参数是null/undefind,默认指向Window全局对象; apply和call改变完this后会执行函数,而bind只会返回改变完this的新函数;
4)new绑定
当new来实现构造函数调用时,依次执行以下几步: 1. 创建(或者说构造)一个全新的对象。 2. 这个新对象会被执行[[原型]]连接。 3. 这个新对象会绑定到函数调用的this。 4. 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。 其中的第三步,就是把构造函数的this绑定到新的实例对象上并调用,实现属性和方法的继承; - 代码5中:new的过程中this绑定到echo上,因此echo上出现了name属性;
5)4个绑定的优先级:
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定;
//代码0
var a = 1
function foo () {
var a = 2
function inner () {
console.log(this.a)
}
inner()
}
foo()
//代码1
var name = '行星飞行';
let obj = {
name: '听风是风',
fn: function () {
console.log(this.name);
}
};
function fn1(param) {
param();
};
fn1(obj.fn);//行星飞行
//代码2
var name = '行星飞行';
let obj = {
name: '听风是风',
fn: function () {
console.log(this.name);
}
};
let obj1 = {
name: '时间跳跃'
}
obj1.fn = obj.fn;
obj1.fn(); //时间跳跃
//代码3
var obj1 = {
a: 1
}
var obj2 = {
a: 2,
foo1: function () {
console.log(this.a)
},
foo2: function () {
setTimeout(function () {
console.log(this)
console.log(this.a)
}, 0)
}
}
var a = 3
obj2.foo1() //2
obj2.foo2() //3
// 代码4
let obj1 = {
name: '听风是风'
};
let obj2 = {
name: '时间跳跃'
};
var name = '行星飞行';
function fn() {
console.log(this.name);
};
fn.call(undefined); //行星飞行
fn.apply(null); //行星飞行
fn.bind(undefined)(); //行星飞行
//代码5
function Fn(){
this.name = '听风是风';
};
let echo = new Fn();
echo.name//听风是风
4、箭头函数的this绑定
答:
箭头函数相关记住几个规则: 1)箭头函数本身无this,它的this 找上层最接近的作用域的this(就是找上层函数); 2) 箭头函数的this指向的是函数定义时的this,而非执行时(看准何时定义); 3)call、apply和bind无法改变箭头函数this的指向;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。