2015-09-23 9 views
1

Я следовал узел функционального программирует учебник в here, но когда я попытался реализовать свой код для урока # 12, как следоватьлитерал объекта динамического ключа

function Spy(target, method) { 
    var store={}; 
    var self=this; 
    var copy=target[method]; 
    store[target[method]]=0; 
    console.log(store); 
    console.log(store[target[method]]); 
    target[method]=function(){ 
     store[target[method]]+=1; 
     return copy.apply(this,arguments); 
    }; 

    return {count:store[target[method]]}; 
} 

var spy = Spy(console, 'error'); 

console.error('calling console.error'); 
console.error('calling console.error'); 
console.error('calling console.error'); 

console.log(spy.count); 

Я получил console.log(store) в Spy возвращает объект, содержащий функцию , Кроме того, окончательное возвращение return {count:store[target[method]]}; от возврата шпиона не определено. Может кто-нибудь объяснить причины этих двух? Благодаря

ответ

0

Потому что после установки store[target[method]]=0; вы устанавливаете target[method] равной функции, это ухудшит значение store[target[method]] и делает его неопределенным. Похоже, вы хотите использовать значение copy на return:

return {count:store[copy]}; 

Хотя это не помогает, что count все еще будет в этом случае 0. Это связано с тем, что вы возвращаете объект в Spy напрямую {prop: value, ...}, поэтому вы не можете его изменить в пределах функции Spy. Хотя обойти это, определите объект {count:store[copy]} как переменную внутри вашего конструктора (var returnObj = {count:store[copy]};), затем верните эту переменную: return returnObj. Теперь вы можете обновить returnObj.count внутри [target[method]].

Это работает, потому что Object в JavaScript переданы по ссылке.

function Spy(target, method) { 
 
    var store={}; 
 
    var self=this; 
 
    var copy=target[method]; 
 
    store[target[method]]=0; 
 
    var returnObj = {count:store[copy]}; 
 

 
    target[method]=function(){ 
 
     returnObj.count+=1; 
 
     return copy.apply(this,arguments); 
 
    }; 
 

 
    return returnObj; 
 
} 
 

 
var spy = Spy(console, 'error'); 
 

 
console.error('calling console.error'); 
 
console.error('calling console.error'); 
 
console.error('calling console.error'); 
 

 
console.log(spy.count);

+0

Большое спасибо за объяснение и решение :} – seanh

+0

Просто хочу добавить отслеживание после того, как я прочитал http://stackoverflow.com/questions/9437981/why-isnt-this-object-being-passed-by-reference-when-assigning-something-else- это правда, что прохождение объекта в JS должно быть больше похоже на проход по сценарию указателя на C++, чем передача ссылки в C++, поскольку указатель может быть переопределен? – seanh

+0

@seanh Я бы по-прежнему рассматривал его как «пропущенную ссылку», так как это то, как работает его функциональность, но реализовано немного иначе. Он передан [* "копией ссылки * * (http://stackoverflow.com/questions/13104494/does-javascript-pass-by-reference). В основном он передает значение ссылки, поэтому он реализуется как передаваемый по значению, но функциональность действует так, как если бы он был передачей по ссылке. [Значение, переданное в этом случае, является самой ссылкой) (http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language). –

0

Я хотел бы объяснить материал с дополнительными бревнами я поставившие в коде

function Spy(target, method) { 
    var store={}; 
    var self=this; 
    var copy=target[method]; // #0.1 
    store[target[method]]=0; // #0.2 
    console.log('Before :: store', store); // #1 
    console.log('Before :: target[method]', target[method]); // #2 

    target[method]=function(){ 
     store[target[method]]+=1; 
     return copy.apply(this,arguments); 
    }; // #3 

    console.log('After :: store', store); // #4 
    console.log('After :: target[method]', target[method]); // #5 
    return {count:store[target[method]]}; // #6 
} 

var spy = Spy(console, 'error'); 
console.log(spy.count); 

target[method] это функция, которая выглядит как function() { [native code] } (заменить машинный код с некоторым кодом, написанным в js lib).

В 0.2 вы делаете эту функцию (в строгом виде) ключом объекта store и присваиваете его значение 0. Таким образом, ваш объект магазин выглядит как

`Before :: store { 'function() { [native code] }': 0 }` 

в #1 и target[method] является уроженцем функция в #2.

Сейчас, в #3, вы назначаете target[method] новую функцию, так что теперь target[method] будет ссылаться на вашу новую функцию.

Итак, на #4 ваши объекты магазина остаются такими же. (Так как ключ является строгим значением функции.), Который является

`After :: store { 'function() { [native code] }': 0 }` 

, но так как вы сделали назначение в #3, поэтому ваше значение target[method] изменилось к новой функции, которая

After :: target[method] function(){ 
     store[target[method]]+=1; 
     return copy.apply(this,arguments); 
    } 

Сейчас на #6 вы пытаетесь извлечь ключ, который из магазина объекта который не существует в store объект, поэтому он returns undefined и хранить значение счета undefined

+0

Большое спасибо, это имеет смысл сейчас :) Как насчет родного кода, это не похоже на то, что проходит в по вызову Шпиона? – seanh

+0

Собственный код исходит от механизма javascript. Ваш код работает поверх Js Engine, который реализует спецификации ECMA. В этой реализации они представляют собой объект, называемый 'console', который имеет функцию' error'. Эта функция ошибки также имеет некоторую реализацию, а 'in our logs native code' относится к реализации' console.error() '. – guptakvgaurav

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