Почему это не может быть примитивным? - PullRequest
7 голосов
/ 27 января 2012

Я возился с JavaScript и заметил, что this никогда не может быть примитивным. О чем я говорю? Позвольте мне объяснить.

Возьмем, к примеру, эту функцию.

function test(){
    return typeof this;
}
test.call('Abc'); // 'object'
test.call(123); // 'object'

Они оба 'object', а не 'string' или 'number', как я и ожидал.

После небольшого замешательства (и возни с instanceof) я выяснил, что происходит. 'Abc' прикрывается объектом String, а 123 преобразуется в объект Number.

В любом случае, мой вопрос: почему это происходит, и как мне преобразовать объект обратно в его примитив?

Я знаю, что могу использовать (String)this или (Number)this, но как мне это сделать, если я не знаю тип?

РЕДАКТИРОВАТЬ : Я пытался сделать это:

function element(){
    var $e = $(this),
    $d = $e.closest('div');
}
element.call('#myID');

и это не сработало. this - это String объект, и jQuery просто создал коллекцию объектов вместо использования селектора для поиска в DOM.

Ответы [ 4 ]

5 голосов
/ 27 января 2012

Как отмечали другие, он приводится к объекту согласно спецификации.

Важно отметить, что если вы находитесь в строгом режиме , принуждение не происходит.

"use strict";

function test(){
    return typeof this;
}
test.call('Abc'); // 'string'
test.call(123); // 'number'

Таким образом, реальный вопрос - , почему вы не используете строгий ?; -)


Как вы отметили в своем комментарии, вы сможете использовать .valueOf(), если вы поддерживаете реализации, которые не поддерживают строгий режим.

Если вывы ожидаете только строку или если вы также ожидаете число, но вместо этого вы не возражаете против числовой строки, вы можете сделать это ...

(this + '') // "Abc"
(this + '') // "123"

«но как я могу это сделать, если я не знаю тип»

Если вы хотите узнать его тип, используйте общий toString, доступный в Object.prototype, чтобы получитьвнутреннее [[Class]] свойство.

Object.prototype.toString.call( this ); "[object String]"
Object.prototype.toString.call( this ); "[object Number]"
3 голосов
/ 27 января 2012

Я нашел это, ECMAScript 5.1

Function.prototype.call

ПРИМЕЧАНИЕ Значение thisArg передается без изменений как значение this. Это изменение по сравнению с выпуском 3, где undefined или null thisArg заменяется глобальным объектом, а ToObject применяется ко всем другим значениям, и этот результат передается как значение this.

Как правило, в качестве первого параметра указывается undefined и null, поэтому this является глобальным объектом (window в контексте браузера), а все остальные значения преобразуются в объект с использованием ToObject.


Из-за несоответствия typeof я рекомендую использовать Object.prototype.toString.call, который возвращает непротиворечивые значения в каждом браузере, который я тестировал:

Object.prototype.toString.call('foo') //[object String]
Object.prototype.toString.call(10000) //[object Number]
Object.prototype.toString.call(someFunc) //[object Function]
...etc

вы можете сравнить выходные данные в этой скрипке

2 голосов
/ 27 января 2012

Спецификация говорит , что this всегда является объектом.

В противном случае, если Type (thisArg) не является Object, установите ThisBinding на ToObject (thisArg).

0 голосов
/ 27 января 2012

Насколько я понимаю, this не имеет смысла вне объектно-ориентированного контекста, он всегда будет указывать на экземпляр какого-либо объекта. Так что по определению это не может быть примитив.

Кроме того, похоже, что ваша тестовая функция возвращает саму typeof функцию test (в данном контексте this), а не параметры, которые вы передаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...