构造函数之外的JavaScript OOP原型?

构造函数之外的JavaScript OOP原型?,javascript,oop,Javascript,Oop,我在阅读developer.mozilla.org的OOP JS指南时发现了以下代码片段: function Person(gender) { this.gender = gender; } Person.prototype.gender = ''; Person.prototype.sayHello = function () { alert ('hello'); }; var person1 = new Person('Male'); var person2 = new Per

我在阅读developer.mozilla.org的OOP JS指南时发现了以下代码片段:

function Person(gender) {
  this.gender = gender;
}

Person.prototype.gender = '';

Person.prototype.sayHello = function () {
  alert ('hello');
};

var person1 = new Person('Male');
var person2 = new Person('Female');

// call the Person sayHello method.
person1.sayHello(); // hello
我不明白,如果(性别)已经被定义为这个;为什么我们需要把Person.prototype.gender='';线路?我理解构造函数之外的函数,但这行代码似乎在重复this.gender;线路。我知道它是在将性别作为Person()对象的属性创建,但这不就是重复this.gender吗


如果您能给我解释一下,我将不胜感激,因为我是OOP JS新手。谢谢

简单的回答是,该行仅用于默认值,您实际上是在执行以下操作:

function Person(gender) {
  this.gender = gender || '';
}

Person.prototype.sayHello = function () {
  alert ('hello');
};

var person1 = new Person('Male');
var person2 = new Person('Female');

// call the Person sayHello method.
person1.sayHello(); // hello
如果您创建了一个人,但未传入性别,则this.gender设置为undefined

因此,当您查找属性时,它将查找对象本身的属性。这将被证明是未定义的,因此它将尝试在原型上查找它,并找到未定义的空字符串


因此,在这种情况下,它只是一个默认值,完全可以不使用此模式,只对方法使用原型,而不使用值。

通过添加
Person.prototype.gender=''此人具有“默认”性别。如果在实例化时没有指定性别,则更像是为人定义性别。请记住,未定义
gender
时,设置
this.gender=gender
仍视为指定值

如果您试图从您的个人中删除
gender
属性,则情况会变得明显。如果
Person.prototype.gender=''被省略,则可能出现以下情况:

var person1 = new Person('Male');

// check gender
person1.gender === 'Male'; // true

// remove gender property from person1
delete person1.gender;

person1.gender === undefined; // true
由于
person1
不再具有
gender
,因此它无法在这个Person实例中引用它,因此它将在Person构造函数中查找其原型链。它不会在那里找到它,因为在构造函数中
this.gender=gender是一个实例属性。查找过程在原型链上继续,直到找到属性为止

现在考虑如果我们有以下内容:

function Person(gender) {
  this.gender = gender;
}

Person.prototype.gender = 'Asexual';

var person1 = new Person('Male');
var person2 = new Person('Female');
var person3 = new Person();

// check genders, looking at instance property
person1.gender === 'Male'; //true
person2.gender === 'Female'; //true
person3.gender === undefined; //true

// remove their genders
delete person1.gender;
delete person2.gender;
delete person3.gender;

// check genders again, now it's looking up the prototype chain 
person1.gender === 'Asexual'; //true
person2.gender === 'Asexual'; //true
person3.gender === 'Asexual'; //true

也许稍微不同的语法有助于定义您所询问的默认值

var Person = (function () {
    function Person(gender) {
        this.gender = gender || '';
    }
    Person.prototype.greet = function () {
        return "Hello, " + this.gender;
    };
    return Person;
}());

// Create instance
var greeter = new Person();

假设您使用
person2=new Person()
调用OP的代码,那么
person2.gender
undefined
,因为它被设置为
undefined
(它是一个属性设置为
undefined
),只有当您调用
delete person2.gender
时,属性
gender
才被取消设置,然后将查找原型的值,并在这种情况下返回
'
。因此拥有
this.gender=gender
将不会使用
Person.prototype.gender=''为默认值。如果未传递任何参数,则此.gender不会默认为原型值,则设置Person.prototype.gender有什么意义?我已经在有Person.prototype.gender行和没有Person.prototype.gender行的情况下运行了代码,并且它以任何一种方式工作,因此我认为如果没有传入任何参数,则默认为prototype值是有意义的,但既然不是这样,那么它的意义何在?在本例中,您不需要它。通常,只有在仅有条件地创建属性并从原型继承默认值的情况下,才会执行此操作。虽然这确实是技术性的,与您的问题没有直接关系,但这可能会引起您的兴趣:。非常感谢,这正是我想要的。Object.Prototype.Property是一个后备属性,这是有道理的。