1

我以为我知道 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构造函数及其原型不像其他原型那样“可访问”。在 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!

其次
,还有其他类似行为的对象吗?

4

3 回答 3

2

的值this完全由函数的调用方式或Function.prototype.bind设置。

在 valueOf 方法中, this 将指向函数对象,因为我正在定义函数对象的属性。

不,不是。在函数中,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设置方式无关,而与弄乱宿主对象及其属性有关。

于 2012-09-21T14:08:04.583 回答
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
于 2012-09-21T14:21:07.447 回答
0

我在想,因为window.location它是一个宿主对象,它不遵守“本机”JS 对象语义,这就是为什么你在location做与foo.

http://jibbering.com/faq/#nativeObject

于 2012-09-21T14:27:42.343 回答