JS: "this" в контексте функции в строгом режиме, спецификация MDN не соответствует реализации chrome 67
От MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this, это говорит:
В строгом режиме, однако, значение этого остается на том, что было установлено при входе в контекст выполнения, поэтому в следующем случае это будет по умолчанию неопределенное:
function f2() {
'use strict'; // see strict mode
return this;
}
f2() === undefined; // true
Это говорит о том, что если я (1) "использую строгий"; и (2) определить f2 внутри другой функции, которая при вызове f2 свяжет внешнюю функцию this для f2. НО!
Это не работает...
'use strict';
function AlarmClock(clockName) {
this.clockName=clockName;
}
console.log("hello, let's see some weird stuff");
console.log("THIS in global", this);
AlarmClock.prototype.start = function(seconds) {
console.log('outer', this);
var testInside = function() {
console.log('inner', this);
}
testInside();
}
var clock = new AlarmClock("Horizons")
clock.start(1);
// WITHOUT CONSTRUCTORS
function withoutOut() {
console.log("withoutOut", this)
this.howard="notSoBad";
console.log("modifiedTheThis, should have Howard", this)
function withoutIn1() {
console.log("withoutIn1", this);
console.log("Strict should set to the defining object's this");
}
var withoutIn2 = function() {
console.log("withoutIn2", this);
console.log("Strict should set to the defining object's this");
}
withoutIn1();
withoutIn2();
}
withoutOut.bind({Moose: "genius"})();
console.log("DONE");
Дает этот вывод:
hello, let's see some weird stuff
THIS in global {}
outer AlarmClock { clockName: 'Horizons' }
inner undefined
withoutOut { Moose: 'genius' }
modifiedTheThis, should have Howard { Moose: 'genius', howard: 'notSoBad' }
withoutIn1 undefined
Strict should set to the defining object's this
withoutIn2 undefined
Strict should set to the defining object's this
DONE
ПРИМЕЧАНИЕ: я запустил это с узлом v10.5.0 из командной строки Mac OSX.
ПРИМЕЧАНИЕ 2: Если вы работаете в devtools, вы должны следовать этим шагам для строгого использования.
ПРИМЕЧАНИЕ 3: По сути, я хочу найти способ проникнуть внутрь, без IN1 или без IN2, чтобы НЕ быть неопределенным. И я знаю, что вы можете сделать это с явным связыванием, но я хочу конкретно получить поведение, указанное в документе MDN.
Если вы согласны со мной, MDN следует изменить документ "this", чтобы просто сказать, что в контексте функции с "use strict" это значение установлено ВСЕГДА ВСЕГДА. (автору нравится)
Или Chrome должен изменить реализацию. (автор не любит)
1 ответ
Значение this
когда функция вызывается, она не имеет ничего общего с тем, как или где она определена. Это связано только с тем, как вызывается функция. Вызов ваших внутренних функций:
AlarmClock.prototype.start = function(seconds) {
console.log('outer', this);
var testInside = function() {
console.log('inner', this);
}
testInside();
}
лайк testInside()
без какой-либо ссылки на объект означает, что нечего связывать this
и в строгом режиме это означает this
является undefined
, Однако, если вы написали вместо
testInside.call(this);
тогда будет значение контекста. Тот факт, что функция находится "внутри" другой функции, опять же, абсолютно не влияет на то, как this
связан. В качестве альтернативы:
this.testInside = testInside;
this.testInside();
это также сработало бы, потому что снова есть контекст.
О, а также также, новый (ish) механизм функции стрелки позволяет вам создавать функции, которые эффективно "наследуют" this
значение из их лексической среды. Так:
AlarmClock.prototype.start = function(seconds) {
console.log('outer', this);
var testInside = () => {
console.log('inner', this);
}
testInside();
}
будет работать, потому что вызов функции стрелки не требует каких-либо this
связывание; this
ведет себя по существу как переменная в замыкании.