这又是一个面试经典问题~/(ㄒoㄒ)/~ ~也是ES5中众多坑中的一个,在ES6中可能会极大避免这个产生的错误,但是为了一些老代码的维护,最好还是了解一下这个的指向和调用,应用,结合三者的区别。
在ES5中,其实这的指向,始终坚持一个原理:这个永远指向最后调用它的那个对象,来,跟着我朗读三遍:这永远指向最后调用它的那个对象,这永远指向最后调用它的那个对象,这永远指向最后调用它的那个对象。记住这句话,这你已经了解一半了。
下面我们来看一个最简单的例子:
例1:
var name=皐indowsName”; 函数(){ var name=坝L摇? console.log (this.name);//windowsName 控制台。日志(“内部:" +);//内部:窗口 } (); 控制台。日志(“外:“这+)//外:窗口
这个相信大家都知道为什么日志的是windowsName,因为根据刚刚的那句话“这永远指向最后调用它的那个对象”,我们看最后调用一个的地方();,前面没有调用的对象那么就是全局对象窗口,这就相当于是window.a();注意,这里我们没有使用严格模式,如果使用严格模式的话,全局对象就是未定义的,那么就会报错未捕获TypeError:无法读取属性的名称定义。
再看下这个例子:
例2:
var name=皐indowsName”; var={ 名称:“樱桃”, fn:函数(){ console.log (this.name);//樱桃 } }a.fn ();
在这个例子中,函数fn是对象一个调用的,所以打印的值就是一个中的名称的值。是不是有一点清晰了呢~
我们做一个小小的改动:
例3:
var name=皐indowsName”; var={ 名称:“樱桃”, fn:函数(){ console.log (this.name);//樱桃 } }window.a.fn ();
这里打印樱桃的原因也是因为刚刚那句话“这永远指向最后调用它的那个对象”,最后调用它的对象仍然是对象。
我们再来看一下这个例子:
例4:
var name=皐indowsName”; var={//名称:“樱桃”, fn:函数(){ console.log (this.name);//定义 } }window.a.fn ();
这里为什么会打印定义呢?这是因为正如刚刚所描述的那样,调用fn的是一个对象,也就是说fn的内部的这是对象,而对象一个中并没有对名字进行定义,所以日志的this.name的值是未定义的。
这个例子还是说明了:这永远指向最后调用它的那个对象,因为最后调用fn的对象是,所以就算一个中没有名字这个属性,也不会继续向上一个对象寻找this.name,而是直接输出定义。
再来看一个比较坑的例子:
例5:
var name=皐indowsName”; var={ 名称:空,//名称:“樱桃”, fn:函数(){ console.log (this.name);//windowsName } } var f=a.fn; f (),
这里你可能会有疑问,为什么不是樱桃,这是因为虽然将一个对象的fn方法赋值给变量了,但是没有调用,再接着跟我念这一句话:“这永远指向最后调用它的那个对象”,由于刚刚的f并没有调用,所以fn()最后仍然是被调窗用的,所以这指向的也就是窗口。
由以上五个例子我们可以看的出,这的指向并不是在创建的时候就可以确定的,在es5中,永远是这永远指向最后调用它的那个对象。
再来看一个例子:
例6:
var name=皐indowsName”; 函数fn () { var=坝L摇泵? innerFunction (); 函数innerFunction () { console.log (this.name);//windowsName } } fn ()
读到现在了应该能够理解这是为什么了吧(o # 65439;▽& # 65439;) o。
改变这样的指向我总结有以下几种方法:
<强>使用ES6的箭头函数强>
在函数内部使用_this=这
<强>使用,电话,结合强>
新实例化一个对象
例7:
var name=皐indowsName”; var={ 名称:“樱桃”, func1:函数(){ console.log (this.name) }, func2:函数(){ setTimeout(函数(){ this.func1 () },100); } };//这个a.func2 ()。func1不是一个函数详解JS中的应用,电话,绑定(经典面试题)