Вопрос по arguments, javascript, this – почему код это указывает на объект окна?

4

мой код:

var length = 20;
function fn(){
    console.log(this.length);
}

var o = {
    length:10,
    e:function (fn){
       fn();
       arguments[0]();
    }
}

o.e(fn);

выход20,1кто подскажет почему?

Читать дальшеcall а такжеapply mu is too short
@dbaseman: это было больше оfn() с явнымthis,arguments[0]() человек ведет себя так, как он делает, потому что есть скрытая точка, так что это вроде как сказатьarguments.0() (если последний действительный JavaScript, конечно). mu is too short
При первом звонке вы получаете 20this === window, во-вторыхthis===arguments, Измените console.log наconsole.log(this.length,this); и призыв кo.e(fn,'test'); и вы видите, что вы получаете массив arguments. some
@muistooshort вы говорите оfn() а такжеarguments[0]()один звонитcall и другие звонкиapply? McGarnagle

Ваш Ответ

2   ответа
6

Когдаthis Ключевое слово встречается внутри функции, его значение зависит отhow the function is called.

В твоем случае,fn() вызывается без предоставления значения a this, поэтому значением по умолчанию являетсяwindow. With arguments[0]()контекст являетсяarguments объект, длина которого1.

Дело в том, что это не имеет значенияwhere the function is called, но это важноhow the function is called.

var length = 20;
function fn(){
    console.log(this.length);
}

var o = {
    length:10,
    e:function (fn){
       fn(); // this will be the window.
       arguments[0](); // this will be arguments object.
    }
}

o.e(fn);

Дальше больше, если хотитеthis быть объектомo, вы могли бы использоватьcall или жеapply, или жеbind объект первым.

var length = 20;
function fn(){
    console.log(this.length);
}

var o = {
    length:10,
    e:function (fn){
       var fn2 = fn.bind(this);
       fn.call(this); // this in fn will be the object o.
       fn.apply(this); // this in fn will be the object o.
       fn2(); // this also will be the object o.
    }
}

o.e(fn);
О, и если бы код был в строгом режиме, то была бы выдана ошибка типа, поскольку она не будет установленаthis вwindow если значение не предоставлено (оно будет неопределенным).
@RobG Да, в строгом режиме, это будет неопределенным, когдаfn();
this это не контекст, это компонент контекста исполнения (или лексической среды в ES5). Вы должны были написатьfn() is called without providing a this value, призваниеthis контекст просто сбивает с толку.
2

Давайте немного расширим ваш код:

var length = 20;
function fn() {
    console.log(this, this.length);
}

var o = {
    length: 10,
    e: function(fn) {
        fn();
        fn.call(this);
        arguments[0]();
    }
}

o.e(fn);​

Демо-версия:http://jsfiddle.net/ambiguous/Ckf2b/

Теперь мы можем видеть, чтоthis есть (и, таким образом, гдеthis.length приходит) когдаfn называется. Это дает мне следующий вывод:

DOMWindow 0
Object 10
[function fn() { console.log(this, this.length); }] 1

У нас также есть три способа вызова функцииfn:

  1. fn(): just call it like any old function.
  2. fn.call(this): Use call to force a specific context (AKA this).
  3. arguments[0](): Call fn through the arguments object.

Когда ты сказалfn()нет явного значенияthis в любом месте, так что в браузере, вы получаетеwindow как твойthis, Глобальныйwindow случается иметьlength property:

Returns the number of frames (either frame or iframe elements) in the window.

Вот откуда берется ноль (в моем выводе), вашwindow.length может быть другим.

Мы называемe какo.e(fn) такthis внутриe являетсяoвот чтоo.e(...) средства (за исключением связанных функций и связанных с ними сложностей). Итакthis вfn.call(this) являетсяo и это делаетfn.call(this) такой же (более или менее) какo.fn = fn; o.fn() и мы получаемo а также10 в консоли. Заметили, что точка снова появляется?

fn.call(o) is like o.fn = fn; o.fn()

Третий,arguments[0](), содержит скрытую точку какp = 'm'; o[p] (более или менее) такой же, какo.m такarguments[0]() какfn = arguments[0]; arguments.fn = fn; arguments.fn().

Похожие вопросы