简体   繁体   English

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

[英]Why do we add functions to javascripts prototype?

I am learning javascript. 我正在学习javascript。

Why are functions defined outside of the object? 为什么函数在对象之外定义?

function Man(firstName, lastName) { 

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

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

Looks a bit weird to me. 看起来有点奇怪。 It works if I add the function inside the class (removing .protoype etc) but I am being told to define the function outisde the object. 它可以工作,如果我在类中添加函数(删除.protoype等),但我被告知定义该对象的outisde函数。

Why? 为什么?

Looks a bit weird to me. 看起来有点奇怪。

That's just how setting up the prototypes assigned by constructor functions works. 这就是如何设置由构造函数分配的原型。 And you're not the only one who finds it awkward, see below. 你并不是唯一一个发现它很尴尬的人,见下文。 :-) ( Update: And see further below for how ES6 makes this so much easier.) :-)更新:进一步了解ES6如何让这更容易。)

It works if I add the function inside the class (removing .protoype etc) but I am being told to define the function outisde the object. 它可以工作,如果我在类中添加函数(删除.protoype等),但我被告知定义该对象的outisde函数。

If you do this: 如果你这样做:

function Man(firstName, lastName) { 

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

...then each Man object gets its own copy of the function. ...然后每个Man对象都获得自己的函数副本。 They don't share, you end up with a new function object for each Man object. 它们不共享,最终为每个Man对象提供一个新的函数对象。 (A smart engine can reuse the underlying function code , but there will be two function objects.) The purpose of prototypes is to create features that can be shared by the objects constructed by the constructor. (A智能引擎可以重用的底层功能的代码 ,但有两个功能对象。)原型的目的是创建可由由构造构成的对象共享的功能。

The other great thing about prototypes is that the object's connection to the prototype is ongoing, which means you can add features to objects that already exist, by adding to their prototype. 关于原型的另一个好处是对象与原型的连接正在进行中,这意味着您可以通过添加到原型来向已存在的对象添加功能。 Example: 例:

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"

Note how we added introduction to the prototype after joe was created. 请注意我们如何在创建joe 添加对原型的introduction It doesn't matter, the lookup is dynamic. 没关系,查找是动态的。 When you do joe.introduction , the engine looks for an introduction property on joe and, if it doesn't find it, goes looking on the prototype. 当您执行joe.introduction ,引擎会在joe上查找introduction属性,如果找不到它,则查看原型。 So adding to the prototype later (indirectly) enhances existing objects. 因此,稍后(间接)添加到原型会增强现有对象。


You're not the only one who finds the syntax awkward. 你并不是唯一一个发现语法笨拙的人。 You frequently see people creating " extend " methods like the one in jQuery, Underscore, Prototype, and so on. 您经常看到有人创建“ extend ”方法,如jQuery,Underscore,Prototype等中的方法。 The extend method just assigns properties from a source object to a destination object. extend方法只是将源对象的属性分配给目标对象。 The simple form of it is: 它的简单形式是:

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

...although usually you see something with more features (multiple source objects, returning the destination, etc.). ...虽然通常你会看到更多功能的东西(多个源对象,返回目的地等)。

And then you can use it like this: 然后你可以像这样使用它:

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();
    }
});

That uses object initializer syntax (sometimes called an "object literal"), passes it into extend , and extend puts the properties on Man.prototype . 它使用对象初始化器语法(有时称为“对象文字”),将其传递给extend ,并且extend将属性放在Man.prototype

You also see things like my Lineage script which simplify that syntax further and handle making a few other things (like calling a parent prototype's version of a function) simpler. 你还可以看到像我的Lineage脚本这样的东西,它可以进一步简化语法,并且可以更简单地处理其他一些事情(比如调用父原型的函数版本)。


As of ES6, which is very nearly finalized and is making its way into browsers (you can also transpile), this gets a lot simpler: 从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"

You can define the functions inside the object, but it's not always possible (built-in objects, third-party libraries etc). 可以在对象内定义函数,但并不总是可以(内置对象,第三方库等)。

Presumably the book/tutorial/teacher wants you to use prototype because they want you to learn how to extend objects using that method. 据推测,本书/教师/教师希望您使用原型,因为他们希望您学习如何使用该方法扩展对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM