我编写了一个小脚本,可以将任何给定的类似 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()
直接调用的解决方案,但显然我已经失去了与原始原型内部的所有绑定,因此返回href
on 显式调用就是它所做的一切。
所以我认为我需要将我的自定义应用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 表达的内部关系和代码属性?