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
大家讲道理2017-04-10 14:30:42
你只需要知道this
总是指向调用对象的就可以了,然后我们来分别理解下面的代码:
foo.bar()
,此时的调用对象是foo
,那么this.x=foo.x=20
(foo.bar = foo.bar)()
因为先有一个符号运算,所以相当于如下代码:var fuc = (foo.bar = foo.bar); fuc();
而根据 ECMA手册 所述:The production AssignmentExpression : LeftHandSideExpression
=
AssignmentExpression is evaluated as follows:
- Let lref be the result of evaluating LeftHandSideExpression.
- Let rref be the result of evaluating AssignmentExpression.
- Let rval be GetValue(rref).
- Throw a SyntaxError exception if the following conditions are all true:
- Type(lref) is Reference is true
- IsStrictReference(lref) is true
- Type(GetBase(lref)) is Environment Record
- GetReferencedName(lref) is either
"eval"
or"arguments"
- Call PutValue(lref, rval).
- Return rval.
我们知道赋值运算总返回右边的值。此时的fuc = function () { x = 30; return this.x; }
。运行fuc()
就相当于普通的定义一个函数执行,调用的是全局对象window
,那么此时的this.x = window.x = 10
。
关于等号赋值的文章还可以看看这篇:http://cmc3.cn/n/217.html
(foo.bar, foo.bar)()
同样先有一个符号运算,所以相当于如下代码:var fuc = (foo.bar, foo.bar); fuc();
而根据 MDN手册 所述:The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.
我们知道了逗号运算总是返回最后一个的值。此时的fuc
和第三个是一样的fuc = function () { x = 30; return this.x; }
,所以结果和第三个是一样的。
关于逗号运算的文章还可以看看这篇:http://www.feeldesignstudio.com/2013/09/javascript-comma-operator
天蓬老师2017-04-10 14:30:42
好像被题主引用了呢,尝试重新解释一下吧。。
JavaScript中其实也是分值类型和引用类型的。
一般来说,取引用的值和直接取值的含义是一样的:
比如说在foo = { bar: 233 }
的前提下
console.log(foo.bar)
和
console.log(233)
的含义是一样的。
但是有三个运算符是例外的:
- 赋值号:foo.bar = 874
和233 = 874
意义是不一样的(后者不符合语法)
- delete
:delete foo.bar
和delete 233
意义是不一样的(后者不符合语法)
- 函数调用:即this的问题,题主很清楚的
当我们对引用类型进行操作之后,(在把结果赋给新的引用之前)会自动将引用类型转换为值类型。
这里的操作包括使用函数调用(实参转换为形参的过程),也包括使用运算符(对于原gist就是赋值运算符=
和逗号运算符,
),也包括
再举一个函数调用将引用类型转换为值类型的例子:
var x = 10
var foo = {
x: 20,
bar: function () {
console.log(this.x)
}
}
function execute(func) {
func();
}
foo.bar() // => 20
execute(foo.bar) // => 10
可以看出,foo.bar
这个函数对象当经过函数调用(实参foo.bar
转换为形参func
)之后,引用类型被转换为值类型,this
对象发生变化。
感谢微博上的 @寒冬winter 巨巨的教导。
ringa_lee2017-04-10 14:30:42
前两个输出的 this
指向当前对象,所以输出 20,且题主已理解,所以不多解释。
而第三个和第四个,(foo.bar = foo.bar)()
和 (foo.bar, foo.bar)()
实际上就是
(function () {
var x = 30;
return this.x;
})()
由于这里的 x
前使用 var
,所以匿名函数内部的 x
与 外部变量 x
不同,立即执行函数中的 this
此时指向全局对象,所以 this.x
的值为 10
。如果 foo
定义为:
foo = {
x: 20,
bar: function () {
x = 30;
return this.x;
}
}
此时第三个和第四个例子的输出应为 30
。
this
总共五种情形,建议题主阅读我译的博文:
《细说 Javascript 函数篇(二) : this 的工作机制》
大家讲道理2017-04-10 14:30:42
this具体指向谁,是在这个函数执行时动态确定的,而不是在函数定义时确定的。
同样,Function.apply和Function.call方法均可以动态绑定this。