var x = 10;
一下四个输出第一个和第二个勉强能看懂,第三个和第四个真是理解不了,不明白什么意思
一直听说this指向的是它的所有者,在这个地方套用了下感觉也不太成立
foo = {
x: 20,
bar: function () {
var x = 30;
return this.x;
}
}
console.log(foo.bar()); // 20
console.log((foo.bar)()); // 20
console.log((foo.bar = foo.bar)()); // 10
console.log((foo.bar, foo.bar)()); // 10
你只需要知道
this
总是指向调用对象的就可以了,然后我们来分别理解下面的代码:1. 不多做解释
2. 就相当于
foo.bar()
,此时的调用对象是foo
,那么this.x=foo.x=20
3.
(foo.bar = foo.bar)()
因为先有一个符号运算,所以相当于如下代码:var fuc = (foo.bar = foo.bar); fuc();
而根据 ECMA手册 所述:我们知道赋值运算总返回右边的值。此时的
fuc = function () { x = 30; return this.x; }
。运行fuc()
就相当于普通的定义一个函数执行,调用的是全局对象window
,那么此时的this.x = window.x = 10
。关于等号赋值的文章还可以看看这篇:http://cmc3.cn/n/217.html
4.
(foo.bar, foo.bar)()
同样先有一个符号运算,所以相当于如下代码:var fuc = (foo.bar, foo.bar); fuc();
而根据 MDN手册 所述:我们知道了逗号运算总是返回最后一个的值。此时的
fuc
和第三个是一样的fuc = function () { x = 30; return this.x; }
,所以结果和第三个是一样的。关于逗号运算的文章还可以看看这篇:http://www.feeldesignstudio.com/2013/09/javascript-comma-operator
好像被题主引用了呢,尝试重新解释一下吧。。
JavaScript中其实也是分值类型和引用类型的。
一般来说,取引用的值和直接取值的含义是一样的:
比如说在
foo = { bar: 233 }
的前提下和
的含义是一样的。
但是有三个运算符是例外的:
- 赋值号:
foo.bar = 874
和233 = 874
意义是不一样的(后者不符合语法)-
delete
:delete foo.bar
和delete 233
意义是不一样的(后者不符合语法)- 函数调用:即this的问题,题主很清楚的
当我们对引用类型进行操作之后,(在把结果赋给新的引用之前)会自动将引用类型转换为值类型。
这里的操作包括使用函数调用(实参转换为形参的过程),也包括使用运算符(对于原gist就是赋值运算符
=
和逗号运算符,
),也包括再举一个函数调用将引用类型转换为值类型的例子:
可以看出,
foo.bar
这个函数对象当经过函数调用(实参foo.bar
转换为形参func
)之后,引用类型被转换为值类型,this
对象发生变化。感谢微博上的 @寒冬winter 巨巨的教导。
前两个输出的
this
指向当前对象,所以输出 20,且题主已理解,所以不多解释。而第三个和第四个,
(foo.bar = foo.bar)()
和(foo.bar, foo.bar)()
实际上就是由于这里的
x
前使用var
,所以匿名函数内部的x
与 外部变量x
不同,立即执行函数中的this
此时指向全局对象,所以this.x
的值为10
。如果foo
定义为:此时第三个和第四个例子的输出应为
30
。this
总共五种情形,建议题主阅读我译的博文:感觉这不应该是js的正确写法,模糊不清。
相对还是喜欢Ruby一些,比较清楚。
各种刁钻的写法没必要过分关注吧。
this具体指向谁,是在这个函数执行时动态确定的,而不是在函数定义时确定的。
同样,Function.apply和Function.call方法均可以动态绑定this。