一直以来都知道js的this让初学者很困惑, 但由于在学angularjs的时候潘老师早早的就教我们写代码时先定义self = this
, 然后通过操作self
, 再之后学习angular又一直使用的箭头函数, 所以js的this
用起来和java的用起来并没有什么不同, 也就没有认真的去学习js的this
和其他语言的到底独特在那里, 本周遇到了一个函数尽然不能使用箭头函数, 又想起了这个问题, 就找了几篇博客学了学。
感受一下
让我们先看几段js代码,并猜猜打印的是什么
下面的环境都为chrome的控制台, 即非严格模式(即不使用 use strict
, 两种模式下结果不相同)
// 例子1
function a(){
name: 'yunzhi_a';
console.log(this); //?
}
a();
// 例子2
var b = {
name:"yunzhi_b",
fn:function(){
console.log(this) // ?
}
}
b.fn();
// 例子3
var c = {
name:"yunzhi_c",
fn:function(){
console.log(this); // ?
}
}
window.c.fn();
// 例子4
var d = {
name: 'yunzhi_d',
o: {
name: 'object',
fn: function(){
name: 'fn'
console.log(this); // ?
}
}
}
var j = d.o.fn;
j();
是不是感觉他们都差不多?
公布答案之前, 先说一下this的使用的规则:
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象
例子的答案
例子1
答案是Window
,为什么呢?想想上面的规则,**this的最终指向的是那个调用它的对象**
,函数没有调用对象,这时this
将指向全局的window
对象。
例子2
第二个应该很简单了,还是上面的规则,这次是b
调用的fn
,所以嘛
例子3
第三个呢,是谁调用的fn
,window
吗?再想想
复习一下,this的最终指向的是那个调用它的对象
, fn()
是通过谁调用的,是c
调用的,所以打这时的this指向的就是c
例子4
看着和上面是差不多的对吧?所以答案就是o
对吧?不对
再看看, 我们调用的是j
,虽然他是通过fn
赋的值,但我们确实调用的是前面没有对象的j
, 在例子1
中已经说过了,此时会this
会指向window
。
箭头函数中的this
在使用箭头函数时我们不会遇到这种让人晕乎的this
指向问题
箭头函数保持它当前执行上下文的词法作用域不变,而普通函数则不会。换句话说,箭头函数从包含它的词法作用域中继承到了this
的值。
var object = {
data: [1,2,3],
dataDouble: [1,2,3],
double: function() {
console.log("this inside of outerFn double()");
console.log(this); // object
return this.data.map(function(item) {
console.log(this); // window
return item * 2;
});
},
doubleArrow: function() {
console.log("this inside of outerFn doubleArrow()");
console.log(this); // object
return this.dataDouble.map(item => {
console.log(this); // objecgt
return item * 2;
});
}
};
object.double();
object.doubleArrow();
是不是对map中的函数是谁调用的感到疑惑了?为什么是window
?
因为map中的函数是一个匿名函数,他并没有调用者,想到上面的例子了吧,我们可以看一下map
的基本实现
// Array.map polyfill
if (Array.prototype.map === undefined) {
Array.prototype.map = function(fn) {
var rv = [];
for(var i=0, l=this.length; i<l; i++)
rv.push(fn(this[i]));
return rv;
直接使用的fn()
。
严格模式对this的影响
this
在严格模式下指向undefined
。
大部分情况下,开发者使用 this ,并不希望它指向全局 window 对象。严格模式帮我们在使用this
关键词时,尽量少做搬起石头砸自己脚的蠢事。
修改this指向
开发者可以通过bind
、call
和 apply
来主动控制this的指向,当然这里不再细说,有兴趣可以看这篇文章——JS中call、apply、bind使用指南,带部分原理。。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。