2016-04-02 4 views
1

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

var Person = function() { 
    this.name = "unnamed"; 
} 
Person.prototype.sayName = function() { 
    console.log("My name is " + this.name); 
} 
var Jill = function() { 
    var jill = function() { 
    Person.call(this); 
    this.name = "Jill"; 
    }; 
    jill.prototype = Object.create(Person.prototype); 
    jill.prototype.constructor = jill; 
    jill.prototype.expressJoy = function() { 
    console.log("Huray!"); 
    }; 
    return jill; 
} 
var jill = new Jill(); 
console.log(jill instanceof Jill); // false 
jill.expressJoy(); // error, is not a function 
jill.sayName(); // error, seen if comment out previous line 
+1

'jill' - это фактический конструктор. Не знаю, почему вы завернули это в функцию 'Jill'. Может быть, это должно быть IIFE? – Bergi

+0

Yep, @Bergi - похоже, что у вас была правильная идея. – scader

ответ

2

В вас дела var Jill действует как регулярная функция, а не как конструктор.
Измените код, как показано ниже:

var Jill = (function() { 
    function Jill() { 
     Person.call(this); 
     this.name = "Jill"; 
    }; 
    Jill.prototype = Object.create(Person.prototype); 
    Jill.prototype.constructor = Jill; 
    Jill.prototype.expressJoy = function() { 
     console.log("Huray!"); 
    }; 
    return Jill; 
})(); 

var jill = new Jill(); 
console.log(jill); // Jill {name: "Jill"} 
console.log(jill instanceof Jill); // true 
jill.expressJoy(); // Huray! 
jill.sayName(); // My name is Jill 

Jill Теперь это «реальный» конструктор, который будет генерировать объекты, как вы ожидали. (BTW, имя конструктора должно начинаться с прописной буквы, согласно хорошей практике)

+0

Спасибо, я случайно пропустил эту часть из примера. – scader

+0

@scader, добро пожаловать – RomanPerekhrest

+0

@scader, так что вы знаете, с помощью этого метода вам нужно будет гарантировать, что вы всегда используете 'new' для каждого создания объекта. Если вы вернете «новый jill()» в Jill (как в моем примере), вам не придется беспокоиться о недостатке 'new' и о проблемах, которые могут возникнуть. _Every_ вызов 'Jill()' будет возвращать новый объект. – Andy

1

Вы неправильно инициируя объект,

var jill = Jill(); 
var obj = new jill(); 

Jill Функция возвращает функцию reference не является object. И вдобавок к этому, возвращая функцию ссылки, мы должны создать object для вашего требования.

0

С кодом вам нужно:

1) return new jill(); во внутренней функции, а затем

2) var jill = Jill(); для вызова функции, которая создает новый экземпляр.

DEMO

Это менее сложный метод.

function Person() { 
    this.name = "unnamed"; 
} 

Person.prototype.sayName = function() { 
    console.log("My name is " + this.name); 
} 

function Jill() { 
    Person.call(this); 
    this.name = "Jill"; 
} 
Jill.prototype = Object.create(Person.prototype); 
Jill.prototype.constructor = Jill; 
Jill.prototype.expressJoy = function() { 
    console.log("Huray!"); 
}; 

var jill = new Jill(); 

DEMO

1

Это исправленный код, редактирует с подробным объяснением:

JSBIN Example

// This is your Person class, all "people" will inherit from this object 

var Person = function() { 
    this.name = "unnamed"; 
}; 
// add the sayName function to this prototype 
Person.prototype.sayName = function() { 
    console.log("My name is " + this.name); 
}; 

// now we make a 'Jill' constructor; 
var Jill = function() { 
    Person.call(this); // bind this (Jill) to Person 
    this.name = 'jill'; 
}; 

// create the correct prototype delegation here 
Jill.prototype = Object.create(Person.prototype); 

// the above code, sets Jill's constructor, to Person so we need to set 
// it back to Jill here: 

Jill.prototype.constructor = Jill; 

// add functions on Jill's prototype, these will only be on the Jill object not Person 

Jill.prototype.expressJoy = function() { 
    console.log("Huray!"); 
    }; 

// make a 'Jill' 

var obj = new Jill(); 
console.log(obj instanceof Jill); // true 
obj.expressJoy(); // "Huray!" 
obj.sayName(); // "My name is jill" 

Сейчас более важно, вы смешиваете два типа моделей инстанцирования, прототипичными и псевдоклассический, Человек - последний, а Джилл - первый.

Взгляните на эту удивительную картину из следующего BlogPost Райан Аткинсон:

Blog Post

instantiation Patterns

+0

Эти комментарии больше не имеют смысла – Bergi

+0

верно, исправлено спасибо @Bergi! – JordanHendrix

+0

Спасибо за потрясающую картинку, @Omarjmh. Упрощение объекта имеет смысл.Похоже, что пример, который я использовал, помещал его во IIFE, поскольку они работали над тем, чтобы поместить код в загрузчик модуля. – scader

0

Это должно работать

function Person() { 
    this.name = "unnamed"; 
}; 
Person.prototype.sayName = function() { 
    console.log("My name is " + this.name); 
}; 

function Jill() { 
    Jill.prototype.__proto__ = Person.prototype; 

    this.name = "Jill"; 

    Jill.prototype.expressJoy = function() { 
     console.log("Huray!"); 
    }; 

    return Jill; 
}; 

var jill = new Jill(); 
console.log(jill instanceof Jill); // True 
jill.expressJoy(); // Hurray ! 
jill.sayName(); // My name is Jill 
+0

'__proto__' устарел. Не используйте его. – Bergi