2014-09-05 3 views
0

Я смотрел Pluralsight видео с Дугласом Crockford: http://pluralsight.com/training/Courses/TableOfContents/javascript-good-partsБинарная функция эквивалентности - demethodize

В этом видео он проходит через ряд интересных упражнений, чтобы продемонстрировать некоторые JavaScript принципалов. Когда он попадает в функции «demethodize» вы в основном имеют следующий код:

function add(x,y){ 
    return x + y; 
} 
//add(1,2) => 3 

function methodize(fn){ 
    return function(x){ 
    return fn(this, x); 
    }; 
}; 
Number.prototype.Add = methodize(add); 
//(1).Add(2) => 3 

function demethodize (fn){ 
    return function(x,y){ 
    return fn.call(x,y); 
    }; 
} 
var newAdd = demethodize(Number.prototype.Add); 
// newAdd(1,2) => 3 

Заметьте, что эта функция «demethodize» является только для бинарных функций.

Мой вопрос заключается в том, что, по моему пониманию, следующее должно привести к эквивалентным «demethodise» функций:

function demethodize (fn){ 
    return fn.call; 
} 

или

var demethodize = Number.prototype.Add.call; 

Но эти функции не работают (с учетом то же требование бинарной функции)! Почему это?

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

ответ

1

Результат вашего demethodize функции является Function.prototype.call функция - не связана с вашей fn, то есть без каких-либо this value (который он имел, если он был вызван в качестве fn.call(…)). Однако вы можете использовать , чтобы исправить это:

function demethodize(fn) { 
    return Function.prototype.call.bind(fn); 
} 
// or long: 
function demethodize(fn) { 
    return function(context/*, args... */) { 
    var args = Array.prototype.slice.call(arguments, 1); 
    return fn.apply(context, args); 
    // equivalent (for binary functions) to 
    return fn.call(context, args[0]); 
    //  ^^^^^^ is a method invocation here 
    }; 
} 
1

Потому что call не знает, на какой функции он должен называться. Взгляните на MDN documentation на то, как работает this.

Это то же самое, как

var foo = {bar: function() { console.log(this); }}; 
foo.bar(); // logs foo 
var bar = foo.bar; 
bar(); // logs window 

Вы изменили способ, как .call выполняется и что вы изменили, что this относится.

Смежные вопросы