各位小伙伴在面试中被面试官问道this指向问题必定很多吧,同时还被问道apply,call和bind的用法区别,如今,就来简单的聊一聊this到底指向何方。html
1.基本概念面试
MDN的官方解释:与其余语言相比,函数的 this
关键字在 JavaScript 中的表现略有不一样,此外,在严格模式和非严格模式之间也会有一些差异。在绝大多数状况下,函数的调用方式决定了this
的值。this
不能在执行期间被赋值,而且在每次函数被调用时this
的值也可能会不一样。数组
简而言之:浏览器
1.this指向的对象称为函数的上下文对象context; app
2.this的指向取决于函数被调用方式 函数
无论函数怎么调用的天花乱坠,咱们只要记住这几点便可清晰的找出this的指向。this
2.小试牛刀spa
function foo(){ console.log(this); }
面试官问你this指向哪里,固然大声回答不知道,缘由:谁调用指向谁,函数都没被调用,确实不知道指向。code
小结:直接经过函数名来调用函数,this指向全局变量window;经过对象.函数名调用函数,this指向该对象。htm
3.DOM对象调用函数时this的指向问题
1.经过选择器选择元素加事件属性来绑定事件,this指向该DOM对象,例子以下:
document.getElementById('btn').onclick=function(){ console.log('click'); //click console.log(this); //<button id="btn">button</button> }
2.直接在DOM标签中写事件,this指向window,咱们能够经过吧this做为参数传入方法中再使用,例子以下
html: <button onclick="modify()">add</button> <span id="count">0</span> <button onclick="modify()">reduce</button> script: // 操做方法 function modify(){ console.log(this); //window }
由于这个时候是直接调用方法的,因此this指向全局window对象,那么问题来了,咱们想判断咱们点击的是哪个按钮,应该怎么作呢,咱们能够把this的值做为参数传入方法中再使用,例子以下。
html: <button onclick="modify(this)">add</button> <span id="count">0</span> <button onclick="modify(this)">reduce</button> script: // 操做方法 function modify(_this){ console.log(_this); // <button onclick="modify(this)">add</button> // <button onclick="modify(this)">reduce</button> }
4.对象中this的指向问题
先看一个简单的例子:
var a=1; function printA(){ console.log(this.a); } var obj={ a:2, foo:printA, bar:function(){ printA(); } } obj.foo(); //2 obj.bar(); //1
var foo=obj.foo;
foo(); //1
咱们定义了一个全局变量a和一个打印a的全局变量方法,以后又定义了一个obj对象,其中包含a属性和foo,bar两个方法。当咱们调用obj.foo()打印了2,调用obj.bar()打印了1.
分析:
无论printA在哪里定义的,咱们this的指向只取决于被谁调用的。在obj.foo(),foo的属性值为printA,被obj直接调用,因此this指向obj,this.a就是obj.a=2了;
当咱们调用obj.bar()时,bar的属性值为function(){printA()},没有明确哪一个对象来调用printA方法,this默认指向全局对象window,因此this.a=window.a=1;
第三种状况咱们把obj.foo值赋予了foo变量,在调用的时候就至关因而window.foo()了,打印1。
小结:this的指向不是函数声明是绑定的,而是在函数运行过程当中动态绑定的。
5.改变this的指向方法:applay call bind
话很少话:写了一个例子,你们先看,万一比喻不恰当,你们能理解其中意思便可
var liLei={ name:'liLei', money:10, buyPen:function(){ this.money=this.money-1; console.log(this.name+" have money:"+this.money) } } var hanMeiMei={ name:'hanMeiMei', money:20, buyPan:function(){ this.money=this.money-2; console.log(this.name+" have money:"+this.money) } } liLei.buyPen(); // liLei have money:9 hanMeiMei.buyPan(); //hanMeiMei have money:18
例子很好理解,输出的结果相信你们也能看得明白,哪天,韩梅梅想买一个盆,她买不了,由于她尚未这个方法,她一想:我没有这个方法,可是李雷有啊,我打电话给李雷把钱他让他帮我买啊;后来李雷想买一个盘,实现方法也是如此。那么,在代码中如何实现呢?
JavaScript有好几个方法能够实现:call,apply,bind。
call方法:
语法:call(thisObj,Object)
定义:调用一个对象的一个方法,以另外一个对象替换当前对象。
说明:
call 方法能够用来代替另外一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。若是没有提供 thisObj 参数,那么 Global 对象被用做 thisObj。
liLei.buyPen.call(hanMeiMei); //hanMeiMei have money:19 hanMeiMei.buyPan.call(liLei); //liLei have money:8
apply方法:
语法:apply(thisObj,[argArray])
定义:应用某一对象的一个方法,用另外一个对象替换当前对象。
说明:
若是 argArray 不是一个有效的数组或者不是 arguments 对象,那么将致使一个 TypeError。若是没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用做 thisObj, 而且没法被传递任何参数。
liLei.buyPen.apply(hanMeiMei); //hanMeiMei have money:19 hanMeiMei.buyPan.apply(liLei); //liLei have money:8
bind方法:
liLei.buyPen.bind(hanMeiMei)(); //hanMeiMei have money:19 hanMeiMei.buyPan.apply(liLei)(); //liLei have money:8
小结:三种方法的相同指出是:能够改变this的指向,不一样之处是:apply接受的参数为一个数组,call接收的参数为一个个独立的值;apply,call会直接调用方法,bind改变this的指向返回一个方法不调用。
注:有些低版本的浏览器不支持函数使用bind方法,咱们在作浏览器兼容时能够加以判断,具体实现方法暂不赘述。
以上就是我的对于this的指向问题的理解,咱们只需记住一点:this指向-谁调用,指向谁。不得不说JavaScript真是个奇妙的世界,文中有纰漏不足的地方,欢迎指正。
参考资料:
转载请注明出处,谢谢!