2011-12-21 2 views
1
var foo = { 
    bar: function() { return this.baz; }, 
    baz: 1 
    }; 
    (function(){ 
    return typeof arguments[0](); 
    })(foo.bar); 

Почему этот код возвращает undefined?Функции Аргументы Пассивы и возвраты

Я бы предположил, что arguments[0] будет содержать foo.bar, что является функцией. При вызове через arguments[0]() он должен вернуть результат оценки функции в этом случае 1. Следовательно, typeof arguments[0]() должен вернуть «Номер» (например, typeof 1). Вместо этого он возвращает undefined. Зачем?

ответ

-2

это относится к самой функции бара.

var foo = { 
    bar: function() {return foo.baz; }, 
    baz:1 
    }; 
    (function(){ 
    return typeof arguments[0](); 
    })(foo.bar); 

скрипку: http://jsfiddle.net/W9Jqb/

+1

Это не так. Ключевое слово 'this' указывает на контекст выполнения. В данном примере это область анонимной функции, которая ее вызывает. Так как сам он вызывается из глобальной области, 'this' просто указывает на глобальный объект' window'. – PPvG

+1

Было бы неловко, если бы у нас было много функций в этом объекте, и мы хотели изменить имя foo :) – abuduba

+1

Почему это принятый ответ? Я думал, что вопрос: «Почему этот код возвращает« undefined »?» *, Not * «Можете ли вы помочь мне найти уродливый хак, чтобы исправить это?» *. – PPvG

5

код не будет работать, потому что внутри анонимной функции вы теряете ссылку на this.baz объекта Foo при использовании в другом контексте

вы можете использовать метод apply() переопределить контекст, как и

var foo = { 
    bar: function() { return this.baz; }, 
    baz: 1 
}; 

(function(){ 
    return arguments[0].apply(foo); 
})(foo.bar); 

и это возвращает правильно 1, потому что применять() метод изменения контекста выполнения для объекта, переданного в качестве аргумента

typeof arguments[0].apply(foo); 

возвращает number как ожидалось

+0

возвращения TYPEOF аргументов [0] .Не (foo), я думаю, это было то, что вы имели в виду. Я вижу удобство применения и значение контекста исполнения, вступающего в картину. –

8

Чтобы понять, почему this не является ссылкой на объект, на котором функция проживает, вы должны понимать, что JavaScript не имеет классов. Он имеет функции.

В JavaScript функции никогда строго не привязаны к объектам, как они есть в таких классных языках, как Java, C#, что угодно. Функция javascript - это еще один тип, такой как string и number, что означает, что вы можете передавать функции вокруг переменных, подобных любому другому типу. В вашем примере функция, содержащаяся в foo.bar, вообще не знает о foo. Это просто функция, учитывающая собственный бизнес.

И что же делает ключевое слово this? Он указывает на контекст . В вашем примере вы вызываете функцию внутри foo.bar из глобальной области (то есть window), поэтому на это указывает. Вы можете использовать apply() для вызова функции в правильной области, но для этого вам потребуется доступ к этой области (в данном случае объект foo). Это отрицает любые преимущества безопасности при прохождении только функции без объекта.

Чтобы исправить эту «проблему», в ECMAScript 5 (будущая версия JavaScript) вводится . Эта удобная функция позволяет связать функцию определенного объема выполнения перед передачей его в другую функцию, например:

var foo = { 
    bar: function() { return this.baz; }, 
    baz: 1 
}; 

var callback = foo.bar.bind(foo); 

(function(){ 
    return typeof arguments[0](); 
}(callback)); 
+0

Также обратите внимание, что 'bind()' фактически будет работать в большинстве современных браузеров, сегодня: http://jsfiddle.net/54dzA/. За исключением того, что мы не можем использовать его, потому что IE 6 его не поддерживает. Или IE 7. Или IE 8. – PPvG

1

Вы можете В обув по this заявления.

Вы должны написать обертку, как показано ниже, которая будет очень полезно, если будут мы хотели изменить имя в обув, когда мы будем иметь много функций в обув

var foo = { 
    bar: function() { return this.baz; }, 
    baz: 1 
    }; 

(function(a){ 
for(var i in a){ 
    if(typeof a[i] === "function"){ 

     a[i] = (function(f){ 
      return function(){ 
       return f.apply(a,arguments); 
      } 
     })(a[i]) 
    } 
} 
})(foo); 

    (function(){ 
    return typeof arguments[0](); 
    })(foo.bar); 
Смежные вопросы