这是我参与8月更文挑战的第N天,活动详情查看:8月更文挑战
什么是this?
通常this的指向分为很多种情况,下面我们一一 来介绍:
1. 默认情况(默认绑定)
默认的this
console.log(this); // window,这里不区分严格模式和非严格模式,都是指向window
在默认情况下,this指向window
函数中的this
"use strict";
function fn(){
console.log(this);//非严格模式指向window,严格模式指向undefined
}
fn();
在严格模式下,函数中的this是undefined,但是在非严格模式下,函数中的this指向window
2. 隐式绑定
对象方法中的this
1.如果函数调用是在一个对象上触发的,即存在上下文对象,那么这个函数中的this指向调用函数的对象
function sayHi(){
console.log('Hello,', this.name);
}
var person = {
name: 'jack',
sayHi: sayHi
}
var name = 'bob';
person.sayHi(); // Hello,jack
2.需要注意的是,在对象的属性链中,只有最后一个属性会影响函数中的this。(就近原则)
function sayHi(){
console.log('Hello,', this.name);
}
var person2 = {
name: 'jack',
sayHi: sayHi
}
var person1 = {
name: 'bob',
friend: person2
}
person1.friend.sayHi();// Hello,jack
回调函数中的this
1.普通回调函数中
function fn(f){
f();
}
function fn1(){
console.log(this);
}
fn(fn1);
在这个例子中,fn1被作为回调函数调用,回调函数中的this指向和默认绑定的一样,在非严格模式下指向window,在严格模式下指向undefined。
promise中的.then回调也属于普通回调,同样遵循此规则。
2.特殊回调函数(定时器回调函数)
setTimeout(function(){
console.log(this);
});
setInterval(() => {
console.log(this);
},1000);
对于定时器中的回调,不管是在严格模式还是非严格模式下,this稳定指向window。
3.数组遍历方法中的this
var arr=[1,2];
arr.forEach(function(){
console.log(this);
})
在数组的遍历方法中,传入的方法其实也是回调函数,如果在这个方法中不指定替代this对象时,同样非严格模式指向window,严格模式指向undefined。
4.事件回调函数
document.addEventListener("click",clickhandler);
function clickhandler(e){
console.log(this);//侦听事件的对象
}
在绑定事件的回调函数中,回调函数中的this指向被侦听事件的对象。上面的例子中,this就是document对象。
5.使用arguments关键字调用回调函数
function fn(){
arguments[0]()
}
function fn1(){
console.log(this);//this指向fn中arguments
}
fn(fn1);
当在函数中通过arguments调用回调函数时,回调函数中的this指向Arguments对象。
3.call、apply、bind(显式绑定)
call、apply、bind都可以通过传递参数来改变this的指向。
相同点:
-
都可以通过传参改变this的指向,传递的第一个参数就是this
-
如果第一个参数传null或undefined,那么这些值都会被忽略,this的指向就会走默认绑定规则,非严格模式下指向window
不同点:
-
传参不同:
call( this,pra1,pra2,pra3 )
,call传递参数是一个一个传递,而apply第二个参数是一个数组apply( this,[pra1,pra2,pra3] )
-
call和apply在执行时会直接调用函数,而bind不会调用函数。
document.onclick = fn.call(obj); // this改变为obj了,但是绑定的时候立即执行,当触发点击事件的时候执行的是fn的返回值undefined
document.onclick = fn.bind(obj); // bind会把fn中的this预处理为obj,此时fn没有执行,当点击的时候才会把fn执行
4. new 绑定
在JavaScript中,构造函数只是使用new操作符时被调用的普通函数,不属于某个类,也不会实例化一个类。所有的函数都可以通过new来调用,称为构造函数调用。
当使用new来调用函数的时候会自动执行以下操作:
1. 创建一个空对象,构造函数中的this指向这个空对象
2. 执行原型连接 target.__proto__ = constructor.prototype
3. 执行构造函数方法,属性和方法都被添加到this指向的对象上
4. 如果构造函数中没有返回其他的对象,那么就返回this(即创建的这个新对象);否则,返回构造函数中返回的对象。
function Fn(){
this.name = 'jack';
};
let person = new Fn();
person.name//jack
上面这个例子中,这个过程就称为构造调用,this将指向新创建的对象person;
5.箭头函数绑定
箭头函数是ES6新增的,它和普通函数有一些区别,箭头函数没有自己的this,它的this继承于当前函数执行上下文中的this。
在使用箭头函数时,有几点需要注意:
1. 函数中的this,继承的是外层代码块中的this。
2. 箭头函数不能作为构造函数使用new调用,否则会抛出错误。TypeError: fn is not a constructor
3. 不可以使用arguments对象,该对象在函数体内不存在。如果要用可以使用rest参数代替。
// 例1
let fn = (...vals) => {
console.log(vals); // [1, 2, 3]
}
fn(1, 2, 3);
// 例2
let fn = (name, ...vals) => {
console.log(name); // jack
console.log(vals); // [1, 2, 3]
}
fn('jack', 1, 2, 3);
4. 不可以使用yield命令,所有箭头函数不能用作Generator函数。
5. 箭头函数没有自己的this,所以不能用call、apply、bind这些方法去改变this的指向。
总结
- 默认绑定
默认绑定可以理解为函数调用时无任何调用前缀的场景 ,默认绑定的情况下,this指向全局对象window(非严格模式),this指向undefined(严格模式)。
- 隐式绑定
如果函数调用时,前面存在调用它的对象,那么this就会隐式的绑定到这个对象上。如果函数调用前存在多个对象,this指向距离调用自己最近的对象
- 显示绑定
显示绑定就是通过call、apply、bind方法改变this指向。这三个方法传递的第一个参数就是最终的this指向。如果第一个参数是null或undefined,那么this将采用默认绑定的规则,指向全局对象。
- new绑定
使用new绑定时,this指向新创建的那个对象。
- 箭头函数
箭头函数中没有this,箭头函数的this指向取决于外层作用域中的this,外层作用域或函数的this指向谁,箭头函数中的this便指向谁。
例题
- 例1
var obj = {
a: 10,
c: 50,
b: {
a: 0,
c: this.a,
run: function () {
console.log(this.c);
}
}
}
obj.b.run();
- 例2
var length = 10;
function fn() {
console.log(this.length);
}
var obj = {
length: 5,
method: function (fn) {
fn();
arguments[0]();
}
}
obj.method(fn, 1);
- 例3
var name = '222';
var a = {
name: '111',
say: function () {
console.log(this.name)
}
}
var b = {
name: '333',
say: function (fn) {
fn()
}
}
a.say()
b.say(a.say)
- 例4
window.number = 2;
var obj = {
'number': 3,
'db1': (function () {
console.log(this);
this.number *= 4;
return function () {
console.log(this);
this.number *= 5;
}
})()
}
var db1 = obj.db1;
db1();
obj.db1();
console.log(obj.number);
本文参考: 作者:刘小夕 链接:juejin.cn/post/684490…来源:掘金
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!