2016-11-11 4 views
4

Я такой человек, который должен знать все в глубине ... Итак, я проходил много предметов, и я поставил свою ногу в глубины наследия прототипа.
У меня есть четкое представление о том, как это работает в ES5 (каждая функция имеет это свойство специального прототипа, которое указывает на объект, на котором он основан. Этот объект имеет свойство .constructor, которое указывает на функцию и т. Д.). ,Сколько классов ES6 отличается от ES5?

Итак, теперь давайте посмотрим пример ES5:

function Bunny(name) { 
    this.name = name 
} 

Bunny.prototype.sayName = function() { 
    console.log('Im',this.name) 
} 

Это один довольно ясно: функция Банни получает аргумент name который будет назначить на новый объект.

Следующая строка добавляет функцию прототипу функции, которая будет возвращать текущее имя.

Давайте посмотрим класс ES6 Сейчас:

class Fox{ 
    constructor(name){ 
     this.name = name; 
    } 

    sayName() { 
     console.log('Im', this.name) 
    } 
} 

же материал здесь: Constructor здесь, как наша функция Кролика. Но sayName в лисе не то же самое, что и sayName в Bunny.
Давайте создадим экземпляры:

let bunny = new Bunny('Henry'); 
let fox = new Fox('Jerry'); 

И теперь, проверить свои прототипы:

console.log(Object.getPrototypeOf(bunny)) 
console.log(Object.getPrototypeOf(fox)) 

Что мы получаем?

//using repl.it - ES6 
{ sayName: [Function] } 
{} 

Почему?

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

function Bunny(name) { 
    this.name = name 

    //Warning - Bad practice ahead! 
    this.sayName = function() { 
     console.log('Im',this.name) 
    } 
} 

Результат:

//using repl.it - ES6 
{} 
{} 

Это будет иметь смысл, если бы не это:

console.log(bunny.hasOwnProperty('sayName')) 
console.log(fox.hasOwnProperty('sayName')) 

Это означает, fox не владеет sayName на он, либо прототип показывает, что он есть. Я что-то упустил? Почему они разные?

+0

Почему второй пример плохой практики? – evolutionxbox

+0

@evolutionxbox Поскольку он создает новую функцию для каждого экземпляра. –

+0

Никогда не используйте 'console.log' для проверки объекта. Используйте 'console.dir'. –

ответ

7

В классах ES6 все методы неперечислимы, поэтому при регистрации прототипа экземпляра класса ES6 вы получаете то, что выглядит как пустой объект.

Смотрите этот пример:

const obj = new (class {method() {}}); 
 

 
console.log(Object.getPrototypeOf(obj)); // {} 
 
console.log(typeof Object.getPrototypeOf(obj).method); // function

В ES5 вы определяете метод, назначая его к свойству класса прототипа, что делает его перечислит.Если вы хотите, чтобы достичь того же эффекта, как с классами ES6, вы могли бы использовать Object.defineProperty() вместо:

const TestClass = function TestClass() {}; 
 
Object.defineProperty(TestClass.prototype, 'method', { 
 
    value: function() {}, 
 
    writable: true, 
 
    enumerable: false, 
 
    configurable: true, 
 
}); 
 
const obj = new TestClass(); 
 

 
console.log(Object.getPrototypeOf(obj)); // {} 
 
console.log(typeof Object.getPrototypeOf(obj).method); // function


И fox.hasOwnProperty('sayName') возвращает false, потому что hasOwnProperty() проверяет только для собственных свойств, и sayName является в цепочке прототипов. Если вы хотите также проверить свойства в цепочке прототипов, вы можете использовать оператор in: 'sayName' in fox возвращает true.


См. Также Enumerability and ownership of properties на MDN.

+0

Ах, вот что я пропустил! Хороший! Кроме того, я пошел и вставлял свой код в транспондер babel -> получил код в ES5. Существует цикл for, который проходит через все свойства в конструкторе и проверяет, перечислимы ли они -> 'методы' - нет! Проверка его с помощью .propertyIsEnumerable приведет к false. Кроме того, я проверил '.hasOwnProperty' как на' fox', так и на 'fox.prototype' с тем же результатом. Но я не упоминал об этом в своем вопросе, мой плохой. – Krizzu

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