首先this提供了一种更优雅的方式来隐式“传递”一个对象引用,因此可以将API设计得更加简洁并且易于复用。刚刚入门javascript的时候,就不停的听到this多么多么重要balala。。。,最开始觉得也没什么,无非是某些特殊的情况下this指向会混乱, 提前var that=this就好了嘛,但是随着对于js的不断深入理解,this的重要性就会不断凸现出来,也正是由于this 关键字有能力具备多重含义,带来灵活性的同时,也为初学者带来不少困惑,本文就以面试中常见的一些this指向性的面试题为起点,来深入了解下this
一. what is this?
Javascript中的this是当前执行上下文对象的一个属性,在创建执行上下文时生成,在执行上下文中不可改变。但会随着不同执行上下文的不断变化而改变,这也是问题所在。
以 “use strict”; 指定的JavaScript严格模式下,在this没有指向的时候,就赋值为undefined。 在非严格模式下,this在没有具体的指向的时候会指向全局对象,即浏览器运行时的window对象。
非严格模式会因为JavaScript的作用域的和执行上下文的变化导致一些难以排查的问题,因此目前JavaScript从5.1开始逐渐向严格模式倾斜。
JavaScript中的this取决于函数的调用环境和调用方式,后者比前者更重要。同时,this的指向在执行上下文创建的时候是决定不了的,在调用过程中才会决定,通俗点,谁调用,指向谁。
二.JavaScript this 确定规则(从前到后优先级逐渐降低)
首先先讲道理
- 如果使用了new 关键字,this 就是新创建的这个对象;
- 如果使用了函数的abc方法(apply,bind,call),this即为这个明确指定的对象。
- 如果函数使用了明确对象来调用(对象方法),this为这个调用对象。
- 默认,严格模式this为undefined,非严格模式为全局对象(ES6的箭头函数会默认使用外层作用域的this)
三.随便来点简单的
1.function test(){
var name='zhangsan'
console.log(this)//window
console.log(this.name)//undefined
}
test();
复制代码
首先呢,test函数直接被window调用,所以this指向为window对象,test()等价于window.test()
2.
var obj={
name:"张三",
showName:function(){
var name='李四'
console.log(this.name)
}
}
obj.showName()//张三
复制代码
此时,我们通过obj这个对象来调用函数,按照谁调用指向谁这个道理,this此时的指向就是obj
var name="赵五"
3.var obj={
name:"张三",
showName:function(){
var name='李四'
console.log(this.name)//undefined
}
}
var fn=obj.showName
fn()//赵五
(obj.showName=obj.showName)()//赵五
复制代码
接下来皮一下,此时this又被指向回了window,原因是声明变量的时候,函数并没有被上一级对象调用,所以this指向没有被确定(fn相当于该函数的指针),当我们调用fn()的时候,此时仍然是window在调用该函数,所以this又重新指向了window。
(obj.showName=obj.showName)() 根据=从右向左进行赋值 把右边的obj.showName赋值到左边的obj.showName 等价于把右边的匿名函数重新赋值给脸obj.showName 此时 obj.showName整体相当于一个全局变量,这个变量是一个函数性质的变量,再用()调用这个函数时 this指向的是全局变量中的name 输出的是赵五。可以这么理解:var fn=obj.showName;fn() 输出的就是赵五 这个和上面的区别是使用了=号赋值(此时会改变this的指向)操作,上面那个没有进行=号赋值,后面直接进行调用的obj.showName这个匿名函数。
4.var obj={
name:"张三",
item1:{
name:"李四"
showName:function(){
console.log(this.name)//李四
}
}
}
obj.item1.showName()
复制代码
ok,当有多个对象嵌套的时候,尽管外层obj对象是调用的发起者,但是 this始终会指向直接调用它的上一级对象,也就是item1
//做道题吧~
this.name = '李四';
var module = {
name: '张三',
getName: function() { return this.name; }
};
module.getName(); // 张三
var retrieveName = module.getName;
retrieveName(); // 李四
var boundGetName = retrieveName.bind(module);
boundGetName(); // 张三
复制代码
用一道题把上面的知识点都覆盖下,答案很简单谁调用,指向谁,boundGetName相当于module.getName的指针,而我们通过bind方法将该函数关联回了module对象,所以boundGetName函数调用时,this会指向module,最后我们把稍后会为大家讲一下函数的a,b,c(apply,bind,call)方法对于this指向的改变