为什么我们要为javascripts原型添加函数?

时间:2013-07-28 08:20:32

标签: javascript

我正在学习javascript。

为什么在对象之外定义函数?

function Man(firstName, lastName) { 

    this.firstName = firstName; 
    this.lastName = lastName;   
}

Man.prototype.getName = function () {    
    return this.firstName + this.lastName;
};

对我来说有点奇怪。它可以工作,如果我在类中添加函数(删除.protoype等)但我被告知定义该函数outisde对象。

为什么?

2 个答案:

答案 0 :(得分:8)

  

对我来说有点奇怪。

这就是如何设置由构造函数分配的原型。你并不是唯一一个发现它很尴尬的人,见下文。 :-) 更新:,请参阅下文,了解ES6如何让这一切变得如此简单。)

  

如果我在类中添加函数(删除.protoype等),它会起作用,但我被告知要定义函数outisde对象。

如果你这样做:

function Man(firstName, lastName) { 

    this.firstName = firstName; 
    this.lastName = lastName;
    this.getName = function () {    
        return this.firstName + this.lastName;
    };
}

...然后每个Man对象获得该函数的自己的副本。它们不共享,最终为每个Man对象提供了一个新的函数对象。 (智能引擎可以重用底层函数代码,但成为两个函数对象。)原型的目的是创建可由构造的对象共享的特性由构造函数。

关于原型的另一个好处是对象与原型的连接正在进行中,这意味着您可以通过添加到原型来向已存在的对象添加功能。例如:

function Man(firstName, lastName) { 

    this.firstName = firstName; 
    this.lastName = lastName;   
}

Man.prototype.getName = function () {    
    return this.firstName + " " + this.lastName;
};

var joe = new Man("Joe", "Bloggs");
console.log(joe.getName()); // "Joe Bloggs"

Man.prototype.introduction = function() {
    return "Hi there, I'm " + this.getName();
};

console.log(joe.introduction()); // "Hi there, I'm Joe Bloggs"

请注意我们在创建 introduction后如何将joe添加到原型中。没关系,查找是动态的。执行joe.introduction后,引擎会在introduction上查找joe属性,如果找不到,则查看原型。因此,稍后(间接)添加到原型会增强现有对象。


你不是唯一一个发现语法笨拙的人。您经常看到人们创建“extend”方法,如jQuery,Underscore,Prototype等中的方法。 extend方法只是将源对象的属性分配给目标对象。它的简单形式是:

function extend(target, source) {
    var name;
    for (name in source) {
        target[name] = source[name];
    }
}

...虽然通常会看到具有更多功能的内容(多个源对象,返回目的地等)。

然后你可以像这样使用它:

function Man(firstName, lastName) { 

    this.firstName = firstName; 
    this.lastName = lastName;   
}
extend(Man.prototype, {
    getName: function () {    
        return this.firstName + this.lastName;
    },
    introduction: function() {
        return "Hi there, I'm " + this.getName();
    }
});

使用对象初始化器语法(有时称为“对象文字”),将其传递到extendextend将属性放在Man.prototype上。

你还会看到像my Lineage script这样的东西,它们可以进一步简化语法,并且可以更简单地处理其他一些事情(比如调用父原型的函数版本)。


从ES6开始,它几乎已经完成并且正在进入浏览器(你也可以转换),这会变得更加简单:

class Man { 
    constructor(firstName, lastName) {
        this.firstName = firstName; 
        this.lastName = lastName;   
    }

    getName() {    
        return this.firstName + " " + this.lastName;
    }

    introduction() {
        return "Hi there, I'm " + this.getName();
    }
}

var joe = new Man("Joe", "Bloggs");
console.log(joe.getName()); // "Joe Bloggs"

console.log(joe.introduction()); // "Hi there, I'm Joe Bloggs"

答案 1 :(得分:1)

可以定义对象内部的函数,但并不总是可以(内置对象,第三方库等)。

据推测,本书/教师/老师希望您使用原型,因为他们希望您学习如何使用该方法扩展对象。