目录
一、什么是this?
this是JavaScript中的一个关键字,在函数运行期间自动生成的对象,只可以在函数内部使用,表示函数在运行时候的环境对象。
其值在不同的地方表述的含义也不相同,下面做简单介绍。
二、this的值
情景一:纯函数调用
var name = 'lei';
function sayHi(){
var name = 'hahaha'
console.log('hi '+ this.name);
}
sayHi(); // hi lei
window.sayHi();// hi lei
这种情况下相当于全局调用,this指向全局对象。this.指向调用函数的对象。
情景二:作为对象的方法调用
var person =
{
name : 'lei',
sayHi :function(){
var name = 'hahaha';
console.log('hi,' + this.name);
}
}
person.sayHi(); //hi,lei
这种情况下this指向此对象。其实等同于上一种情况,这里的sayHi是函数,其this指向调用函数的对象。
情况三 apply 调用
沿用上面的代码。
sayHi.call(person);
sayHi.apply(person);
apply和call方法,可以使this指向传入的第一个参数。
func.apply(thisArg, [argsArray]) func.call(thisArg, arg1, arg2...)
如果这个函数处于非严格模式下,则指定为
null
或undefined
时会自动替换为指向全局对象,原始值会被包装。
情景四:构造函数中的this
function Person(name, age){
this.name = name,
this.age = age,
this.sayInfo =function(){
console.log('my name is ' + this.name+' and I\'m ' + this.age + ' years old!');
}
}
let me = new Person('lei', 999);
me.sayInfo();
这里设计到原型和原型链,我们先对new操作符做的一些事情进行简单介绍,然后在下一篇文章中给出关于原型及原型链的一些分析。
let me = new Person('lei', 999);
上面代码使用new操作符生成Person的实例,过程如下:
1)let me =new Object() //创建一个空对象,这里的new你先不要管他,学习了原型链之后就知道怎么回事了
2)me.__proto__ = Person.prototype //me继承自Person,把me对象挂在对应的原型链上
3)var obj = Person.call(me) //执行构造函数,这里我们用到了call(),使其this指向me
4)判断执行完构造函数后的返回值,若显式返回一个对象类型,则返回返回此对象,即3)中的obj;否则返回1)中创建的对象me;
if(typeof obj == 'object'){ return obj; }else return{ return me; }
情景五、箭头函数
箭头函数不会创建this,而是沿作用域链从上一级作用域继承this(父级执行上下文,这个概念以后做具体介绍)。
var name = 'lei'
setTimeout(() =>{
var name = 'hahaha';
console.log(this.name)
},1000) // lei
上面实例中,异步调用匿名函数,输出this.name。此时this继承于上一级作用域,也就是全局作用域,返回name属性值。
当遇到多层箭头函数嵌套的时候,只需要沿作用域链找出外层调用箭头函数的对象即是this的指向对象。
最后给出一道题
var a=11
function test1(){
this.a=22;
let b=function(){
console.log(this.a);
};
b();
}
var x=new test1();
//熟悉闭包的同学马上会发现变量b是一个闭包,本质是一个函数
//那么我们参考情景一的情况,会发现找不到它的调用对象,因此在严格模式下其调用对象为undifined,而在非严格模式下,认为其调用对象为window,因此结果为 11;
/**********************************/
var a=11;
function test2(){
this.a=22;
let b=()=>{console.log(this.a)}
b();
}
var x=new test2()
//变量b虽然也是一个闭包,但是箭头函数会继承来自父级执行上下文的this。
那么我们就找找父级执行上下文,参考红宝书中给出的案例,可以知晓其父级上下文为function test1(),那么this指向于test1,因此结果为22;
详细的参考文章:
1、执行上下文:https://segmentfault.com/a/1190000009041008
总结:
(1)this存在于函数中,指向调用对象的对象。
(2)若指向对象不存在,在非严格模式下默认指向全局对象,这个在闭包中常用。严格模式下指向undefined。
(3)箭头函数中无this,因此不能做构造函数,其this继承自父级执行上下文中的this。