1

我编写了一个小脚本,可以将任何给定的类似 URI 的字符串转换为类似于window.location. 这是通过使用 DOM 创建一个锚元素,将传递的字符串分配给它的href属性,然后复制存在于锚元素和window.location元素中的所有静态属性来实现的。

后来我注意到这window.location是一个instanceof神秘的Location对象,但试图调用Location是非法的。为了好玩,我决定重写该Location对象并更改函数的 API 以匹配原生 DOM 构造函数样式。

Location关于 DOM 对象的一个​​很好的(或可怕的,取决于视角)的事情Date之一是它们的非标准实现toString,当调用某些运算符时,它似乎在幕后被调用:

var x = window.location + '?querystring' // => 'http://stackoverflow.com/questions/ask?querystring';

我似乎无法模仿这种行为。

我的第一次尝试是:

Location.prototype.toString = function toString(){ return this.href };

这是我发现的唯一一个模拟window.location.toString()直接调用的解决方案,但显然我已经失去了与原始原型内部的所有绑定,因此返回hrefon 显式调用就是它所做的一切。

所以我认为我需要将我的自定义应用Location到 Location 的本机toString行为中,但是:

Location.prototype.toString = function toStringClosure(){
    // Can't use `Function.prototype.bind` because we need
    // the closure to invoke `this`. Javascript is awesome.
    return ( new Location() ).toString.call( this );
}

…会告诉你执行Location是非法的或无效的。当然。但是关于:

Location.prototype.toString = function toStringClosure(){
    return ( new Date() ).toString.call( this );
}

不,this is not an instance of Date。这意味着在本机对象中具有额外的特权,或者可能只是围绕“我试图寻找 Date.prototype.toString 实际别名为但找不到它们的其他 Date 内部结构”的一个很好的不透明包装器。

但是,在不执行Date 或 Location 构造函数的情况下查询原型会揭示其他内容:

Location.prototype.toString = function toStringClosure(){
    return Location.prototype.toString.call( this );
}

即,Function.prototype.toString is not generic。是的,我知道,这就是为什么我特别提到了非通用Location品种。这使我相信这些对象的内部实际上并没有按照正常的继承规则或确实是 Javascript 执行(毕竟,直接属性分配 withwindow.location = x将隐式执行window.location.assign( x )- 我想这类似于setAttribute某些节点,但是它们基本上保持读写状态)。

那么:有什么方法可以模拟对 Date 和 Location 对象的直接操作所显示的神奇字符串强制转换?

并且:最后 2 段代码如何在内部发挥作用?那里是否存在无法用纯 JS 表达的内部关系和代码属性?

4

1 回答 1

0

在我调查的某个时候,我变得松懈了。我的第一次尝试是:

Location.prototype.toString = function toString(){ return this.href };

…事实证明,这就是所有必要的:当一个对象是一个操作中的一个操作数而另一个操作数不是同一类型时,将依次调用以下属性来查看操作是否可行:

  1. valueOf
  2. toString

Javascript 查找该toString方法,找到它并执行它并在那里尝试操作。所以事实上,在我目前的版本下,如果我运行:

new Location('/root') + '?query=string';

…我会得到:

"http://stackoverflow.com/root?query=string"

排序!

于 2013-09-10T13:44:19.393 回答