Эмулировать приведение к строке, как видно с экземплярами Date и Location

Я написал небольшой скрипт, который преобразует любую заданную URI-подобную строку в объект DOM, подобный тому, который полученwindow.location, Это достигается с помощью DOM для создания элемента привязки, назначая переданную строку его href свойство, а затем скопировать все статические свойства, которые присутствуют как в элементах привязки, так и в window.location элемент.

Я позже заметил, что window.location является instanceof таинственный Location объект, но пытается вызвать Location незаконно Ради интереса я решил переопределить Location измените объект и измените API моей функции в соответствии с собственным стилем конструктора DOM.

Одна из приятных (или ужасных, в зависимости от перспективы) вещей об объектах DOM, таких как Location а также Date это их нестандартная реализация toString, который, кажется, вызывается за кулисами, когда вызываются определенные операторы:

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

Я не могу подражать такому поведению.

Моя первая попытка была:

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

Это единственное решение, которое я нашел, которое подражает window.location.toString() прямой вызов, но, очевидно, я потерял всю привязку к оригинальным прототипам, поэтому возвращаю href при явном вызове это все, что он делает.

Поэтому я подумал, что мне нужно применить свой обычай 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, к которым на самом деле псевдоним Date.prototype.toString, но не смог их найти".

Однако, запрос прототипа без выполнения конструкторов Date или Location показывает что-то еще:

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

А именно, Function.prototype.toString is not generic, Да, я знаю, именно поэтому я специально применил неуниверсальный Location разнообразие. Это заставляет меня поверить, что внутренности этих объектов на самом деле не играют по обычным правилам наследования или выполнения Javascript (в конце концов, прямое присвоение свойств с window.location = x будет неявно исполнять window.location.assign( x ) - Я полагаю, это похоже на setAttribute с определенными узлами, но они остаются по существу для чтения-записи).

Итак: есть ли способ, которым я могу эмулировать магическое приведение строк, отображаемое прямыми операциями с объектами Date и Location?

И: как последние 2 фрагмента кода воспроизводятся внутри? Существуют ли внутренние взаимосвязи и свойства кода, которые не могут быть выражены в чистом JS?

1 ответ

Решение

В какой-то момент в моих исследованиях я потерял сознание. Моя первая попытка была:

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

... И оказывается, что это все, что необходимо: когда объект является операндом в операции, в которой другой операнд не имеет того же типа, следующие свойства будут последовательно вызываться для проверки возможности выполнения операции:

  1. valueOf
  2. toString

Javascript ищет toString метод, находит его, выполняет и пытается выполнить операцию там. Так что на самом деле, под моей текущей ревизией, если я запускаю:

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

…Я получу:

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

Сортировка!

Другие вопросы по тегам