Посилання на ECMA 5 потребує уточнення.
Я припускаю, що це означає ECMA-262 Edition 5. Слід зазначити, що ECMA-262 (він же ECMAScript або, менш точно, Javascript) - загальна сценарна мова, реалізована в Інтернет-браузерах. Від стандарту Edition 5.1:
Наступні кроки виконуються, коли керування входить у контекст виконання для коду функції, що міститься в об'єкті функцій F, абонент, наданий thisArg, і абонент, що надає аргументиList:
- Якщо код функції є суворим кодом, встановіть ThisBinding на цейArg.
- В іншому випадку, якщо thisArg є нульовим або невизначеним, встановіть ThisBinding на глобальний об'єкт.
- В іншому випадку, якщо Type (thisArg) не є Object, встановіть ThisBinding на ToObject (thisArg).
- В іншому встановіть ThisBinding для цьогоArg
- ... (не про "це")
Термін "глобальний об'єкт" відноситься до того, що об'єкт знаходиться у верхній частині ланцюга сфери застосування. Для браузерів це буде "віконний" об'єкт, але це вибір реалізації (у хості Windows Script є невидимий глобальний об'єкт, але немає строгого режиму, тому некваліфіковані посилання отримують доступ до його властивостей, і немає глобального "Я"). Також "суворий режим" повинен бути чітко включений, інакше він не активний (розділ 14.1 стандарту). Як таке, невизначене "це" все-таки вирішиться до глобального об'єкта (вікна) в "ECMA 5", якщо суворий режим не активний.
Тож відповідь на питання:
"це" завжди посилається на об'єкт, що викликає функцію. Якщо функція не викликалася об'єктом (тобто не викликом методу), то "це" (як передано функції) є "невизначеним". Однак якщо НЕ використовує суворий режим, то невизначене "це" встановлюється глобальним об'єктом (правило 2 вище).
"Я" не має особливого синтаксичного значення, це лише ідентифікатор. Браузери, як правило, визначають window.self (лише властивість об'єкта глобального вікна) = window. Це призводить до того, що некваліфіковані посилання на "я" є такими ж, як "вікно" БЕЗ ВАС "самовизначення" було переосмислено в рамках, що додається (наприклад, "var self = this;" вище.
Отже, повне пояснення наведеного вище прикладу:
outer func: this.foo = bar
// "this" refers to the invoking object "myObject"
outer func: self.foo = bar
// "self" resolves to the variable in the local scope which has been set to "this" so it is also "myObject"
inner func: this.foo = undefined
// "this" refers to the invoking object (none) and so is replaced by the global object (strict mode must be off). "window" has no foo property so its "value" is undefined.
inner func: self.foo = bar
// self resolves to the variable in the enclosing scope which is still "myObject"
Цікавий варіант прикладу створює закриття, повертаючи посилання на внутрішню функцію.
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
return function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
};
}
};
var yourObject = {
foo: "blat",
func: myObject.func() // function call not function object
};
console.log("----");
yourObject.func();
Виробництво
outer func: this.foo = bar
outer func: self.foo = bar
----
inner func: this.foo = blat
inner func: self.foo = bar
Зверніть увагу, як внутрішня функція не викликається, поки не викликається вашимObject. Таким чином, this.foo тепер є yourObject.foo, але self все ще вирішує змінну в тій області, що обгороджує, яка на момент повернення внутрішнього об'єкта функції була (і в результаті закриття все ще є myObject). Отже, у внутрішній функції "це" посилається на об'єкт, що викликає внутрішню функцію, тоді як "Я" посилається на об'єкт, який викликав зовнішню функцію для створення посилання на внутрішню функцію.
Для узагальнення резюме підсумків, "це" визначається мовним стандартом, "self" визначається тим, хто його визначає (виконавцем виконання або кінцевим програмістом).