我以为我知道JavaScript的this
关键字是如何工作的,但我又一次感到惊讶。考虑这个片段:
function foo()
{
return 'Foobar';
}
foo.valueOf = function()
{
return this();//this points to foo
};
foo.toString = foo;//alternatively
console.log(foo + '');//logs Foobar as you'd expect
在valueOf
方法中,this
将指向函数对象,因为我正在定义函数对象的属性。但是当我尝试用location
对象做同样的事情时:
location.origin = function()
{
return this.protocol + '//' + this.hostname;
};
location.origin.valueOf = location.origin;
location.origin.toString = function()
{
return this();
}
console.log(location.origin + '/uri');//undefined//undefined/uri ?
console.log(location.origin.toString());//undefined//undefined ?
console.log(location.origin.valueOf());//undefined//undefined ?
实现这一目标的唯一方法是将this()
更改为location.origin()
。任何人都可以解释location
对象的不同之处吗?我可以随意分配属性和方法,但我注意到Location
构造函数及其原型不像其他原型一样“accessible”。在Chrome中,您必须使用Object.getPrototypeOf(location);
,而FF则允许Location.prototype
。
基本上,我有两个问题:
上面的location.origin
内容之间有什么区别:
var foo = {bar:function(){return 'Foobar';}};
foo.bar.valueOf = function(){return this();};
console.log(foo.bar + '');//logs Foobar!
其次是 还有其他任何行为都是这样的吗?
答案 0 :(得分:2)
this
的值完全取决于函数的调用方式或Function.prototype.bind。
在valueOf方法中,这将指向函数对象,因为我正在定义函数对象的属性。
不,不是。在函数中,this
引用foo
,因为你调用函数的方式,而不是你如何定义它。
> location.origin = function() {
> return this.protocol + '//' + this.hostname;
> };
>
> location.origin.valueOf = location.origin;
请注意location
是一个宿主对象。在Safari中,origin
只读,上面什么都不做:
alert(typeof location.origin); // string, not function
Firefox中的结果不同,正如OP中所述。
javascript中的一条黄金法则是:“不要将主机对象视为本机对象”。那是因为它们不一定像本机对象一样。您观察到的行为与设置this
的方式无关,而与处理宿主对象及其属性有关。
答案 1 :(得分:0)
foo.valueOf不指向'foo'而是指向'Foobar'。这是因为 return this(); //后面的括号表示执行foo并最终返回其结果(= foobar)
在第二个例子中, location.origin.valueOf是一个函数
location.origin = function()
{
return this.protocol + '//' + this.hostname;
};
location.origin.valueOf = location.origin(); //<-- Note the parenthesis here
location.origin.toString = function()
{
return this();
}
console.log(location.origin() + '/uri'); //<-- again parenthesis here
console.log(location.origin.toString);// function
console.log(location.origin.valueOf); //<-- parenthesis removed here
答案 2 :(得分:0)
我在想,因为window.location
是一个宿主对象,它不遵守“原生”JS对象语义,这就是为什么你在为location
做同样事情时遇到问题的原因做了foo
。