2013-12-09 2 views
3

Я начинаю больше узнавать о написании JS, используя объект Prototype, но я хочу убедиться, что не нахожу никаких вредных привычек от других разработчиков. Мое понимание использования Prototype - это создание общедоступных методов для вашего экземпляра. Например:Написание JS Prototypes, должны ли все функции использовать объект Prototype?

var module = new Module(); 
module.method(); 

Но я вижу много разработчиков, создающих весь код внутри объекта-прототипа, вещи, которые я хотел бы рассмотреть «частный». Является ли эта плохая практика или считается хорошо? Это просто означает, что я могу:

module.privateFn(); 

Знают ли они об этом? Все хорошо? Любая помощь оценивается. Я просматривал исходный код на GitHub, чтобы попытаться установить лучший путь вперед, вот скрипт, который использует Прототипы для всего (например, attachEvent, которые они явно хотят приватно держали):

https://github.com/WickyNilliams/headroom.js/blob/master/dist/headroom.js

высоко ценится , Я хочу убедиться, что я развиваю, используя правильные реализации.

+1

См http://stackoverflow.com/questions/4736910/javascript-when-to-use-prototypes – mccainz

+0

Все свойства объекта JS являются общедоступными, есть на самом деле не разница. Вы помещаете эти свойства в прототип, который * все экземпляры разделяют *. – Bergi

ответ

0

Прежде всего, вам не нужно писать модули, используя прототип. Подумайте, как если вы пишете что-то вроде класса, вы должны использовать прототипы. А также важно определить, где ваши методы. Определение методов объекта-прототипа и определение их в функции-конструкторе - это совершенно разные вещи!

Давайте посмотрим определение класса образца с помощью методов, определенных в конструкторе:

var Dog = (function() { 
    var Dog = function (age, name) { 
     var that = this; 

     this.age = age; 
     this.name = name; 

     this.sayHi = function() { 
      console.log('Warf! Im ' + that.name); // meaning of "this" changed!!! 
     }; 

     this.anotherMethod = function() {}; 
    }; 

    return Dog; 
}()); 

var puppy = new Dog(1, 'puppy'); // sayHi and anotherMethod created 
var sirius = new Dog(1, 'sirius'); // sayHi and anotherMethod recreated 

sirius.sayHi = function() { console.log('Yohalolop!'); }; 

puppy.sayHi(); // -> 'Warf! Im puppy' 
sirius.sayHi(); // -> 'Yohalolop!' 

Так что есть некоторые проблемы с приведенного выше примера, во-первых методы определяются как любые другие переменные экземпляра. Фактически, вы определяете их как переменную экземпляра, и это означает, что эти функции воссозданы для каждого создаваемого объекта объекта. Я думаю, вы упомянули, что вы не можете использовать ключевое слово в своих определениях методов. Это ошибка склонна, и есть возможность забыть об этом и использовать это ключевое слово ошибкой. Иногда вы можете использовать методы как переменные экземпляра, так же как переменные обратные вызовы.

Давайте посмотрим определение класса образца с объекта-прототипа:

var Dog = (function() { 
    var Dog = function (age, name) { 
     this.age = age; 
     this.name = name; 
    }; 

    // sayHi method defined only once in prototype 
    Dog.prototype.sayHi = function() { 
     console.log('Warf! Im ' + this.name; // we can use this keyword 
    }; 

    // anotherMethod defined only once in protoype 
    Dog.prototype.anotherMethod() { 
    }; 

    return Dog; 
}()); 

var puppy = new Dog(1, 'puppy'); 
var sirius = new Dog(1, 'sirius'); // sirius and puppy sharing same prototype object 

puppy.sayHi(); // -> 'Warf! Im puppy' 
sirius.sayHi(); // -> 'Warf! Im sirius' 

// remember puppy and sirius sharing same prototype object 
Dog.prototype.sayHi = function() { 
    console.log('Yohalolop'); 
}; 

puppy.sayHi(); // -> 'Yohalolop' 
sirius.sayHi(); // -> 'Yohalolop' 

В ответ на ваш вопрос о частных функциях, это сложнее. Да, вы можете использовать частные функции, даже если вы определяете свои методы на прототипе, но есть некоторые проблемы с тестированием. Их использование зависит от вас. Я предпочитаю не использовать. Позвольте мне привести несколько примеров.

var Calculator = (function() { 
    var Calculator = function() { 
     this.importantNumber = 2; 
    }; 

    // There is unfortunately no native implementation 
    // for private methods but you can mimic them with 
    // unaccessible functions and binding. 
    var someExtremeComputations = function() { 
     return 40 + this.importantNumber; // this keyword points to instance because of binding 
    }; 

    Calculator.prototype.getMeaningOfLife = function() { 
     var result = someExtremeComputations.call(this); // we bind function to instance 
     return result; 
    }; 

    return Calculator; 
}()); 

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

Некоторые люди (включая меня) используют префиксное соглашение об именовании underscore для частных методов. Таким образом, они на самом деле являются общедоступными методами, но если кто-то их назвал или переопределив, они были предупреждены префиксом подчеркивания. В конце концов, мы можем тестировать частные методы, поскольку они общедоступны.

var Calculator = (function() { 
    var Calculator = function() { 
     this.importantNumber = 2; 
    }; 

    // private method's name prefixed by an underscore to warn 
    // other developers to be careful about that or not to use. 
    Calculator.prototype._someExtremeComputations = function() { 
     return 40 + this.importantNumber; 
    }; 

    Calculator.prototype.getMeaningOfLife = function() { 
     var result = this.someExtremeComputations(); // no need to bind 
     return result; 
    }; 

    return Calculator; 
}()); 
+0

Спасибо за отличное объяснение. Я читал где-то еще, что использование соглашения об именах подчеркивания было лучшей практикой. – Halcyon991

0

Объяснение этого несколькими словами невозможно. В целом хорошая модель заключается в том, чтобы создавать методы через прототипы, когда вы хотите оптимизировать свой код. Хорошее руководство состоит в том, чтобы вносить самые важные данные в память, использование прототипов имеет решающее значение для этого, поскольку прототипированные переменные и методы не вводятся в память до тех пор, пока вы их не запросите.

Когда приходит ваш пример, прототипов нет.

Простой пример

// new object 
var Dog = function() { 
    var that = this; 

    // add a property 
    that.name = "Fido"; 

    // add a method 
    that.getName = function() { 
     return that.name; 
    }; 
}; 
// ... all the above is stored in memory directly  


// Requires to be constructed 
var dogObj = new Dog(); 
console.log(dogObj.getName()); // Fido 

delete Dog.name // false 
typeof Dog.name // "string" 
delete dogObj.name // true 
typeof dogObj.name // "undefined" 
typeof Dog.name // "string" (still there) 

// Will be available in the dogObj (after you call it) 
dog.prototype.first = "first"; 

// Will be available in the dogObj (after you call it) 
dog.prototype.second = function() { 
    return "second"; 
} 

// Will not be available in dogObj 
dog.third = "third"; 
+0

Спасибо. Таким образом, вы говорите, что вы должны создавать свойства/методы из конструктора Obj и когда вам нужен общий/оптимизированный код (совместное использование объекта-прототипа по сравнению с созданием новых методов многократно известно). Таким образом, ваш ответ будет отрицательным, используйте Prototypes только для этих публичных методов? – Halcyon991

+0

Да, вы не можете прикасаться к частным переменным и методам в исходном объекте. –

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