Чому "це" в анонімній функції не визначено при використанні строго?


85

Чому це в анонімній функції невизначено при використанні javascript у суворому режимі? Я розумію, чому це може мати сенс, але я не міг знайти жодної конкретної відповіді.

Приклад:

(function () {
    "use strict";

    this.foo = "bar"; // *this* is undefined, why?
}());

Тест у скрипці: http://jsfiddle.net/Pyr5g/1/ Перевірте реєстратор (firebug).


4
Зверніть увагу, що це не має нічого спільного з анонімними функціями, але методом виклику. Перегляньте цю змінену скрипту (загляньте в журнал консолі).
Фрогц

@Phrogz: Можливо, звідси виникла певна плутанина. Дякуємо, що вказали на це.
T. Junghans

Відповіді:


101

Це тому, що до ECMAscript 262, випуск 5, була велика плутанина, якщо люди, які, де використовують constructor pattern, забули використовувати newключове слово. Якщо ви забули використовувати newпри виклику функції конструктора в ES3, посилайтеся thisна глобальний об'єкт ( windowу браузері), і ви клобуєте глобальний об'єкт змінними.

Це було жахливою поведінкою, і тому люди в ECMA вирішили, просто взятися за thisце undefined.

Приклад:

function myConstructor() {
    this.a = 'foo';
    this.b = 'bar';
}

myInstance     = new myConstructor(); // all cool, all fine. a and b were created in a new local object
myBadInstance  = myConstructor(); // oh my gosh, we just created a, and b on the window object

Останній рядок видасть помилку в ES5

"TypeError: this is undefined"

(що є набагато кращою поведінкою)


4
Це має сенс. Чи є у вас посилання на резервне копіювання заяви?
Роб W

1
@RobW: Мені довелося б шукати себе, але я кілька разів чув Дугласа Крокфорда, коли він сказав, що це і стало причиною такого рішення.
jAndy

1
Про це згадується в JavaScript: The Good Parts від Crockford. Це докладно описано. Однак не про рішення ECMA.
madr

1
Це логічна причина, чому суворий режим за замовчуванням встановлює це значення як невизначений. Іншою логічною причиною є ефективність, іншою логічною причиною є this === windowзаплутаність і витікання глобального масштабу як
символу

2
@jAndy: Дякую за відповідь. Це має сенс. Я також знайшов компактне пояснення змін до цього на javascriptweblog.wordpress.com/2011/05/03/… : "Найголовніше, якщо перший аргумент, який потрібно викликати або застосувати, є нульовим або невизначеним, це значення викликаної функції не буде перетворено на глобальний об'єкт. "
T. Junghans

15

Існує механізм, який називається "бокс", який обертає або змінює thisоб'єкт перед входом у контекст викликаної функції. У вашому випадку значення thisмає бути, undefinedоскільки ви не викликаєте функцію як метод об’єкта. Якщо режим не суворий, у цьому випадку це замінюється windowоб’єктом. У strictрежимі він завжди незмінний, тому він undefinedтут.

Ви можете знайти більше інформації на
https://developer.mozilla.org/en/JavaScript/Strict_mode


@samuel так як ми можемо призначити змінну об'єкту вікна в суворому режимі ??
Нульовий вказівник

8

Відповідно до цієї відповіді на переповнення стека , ви можете використовувати thisвнутрішні анонімні функції, просто зателефонувавши .call(this)в кінці.

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);

4
Зверніть увагу, що в цьому випадку thisбуде Windowоб’єктом, що може бути
небажаним

Ця відповідь не пояснює поставлене питання.
Анвеш Чека,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.