简体   繁体   English

JavaScript原型对象-如何访问继承

[英]JavaScript prototype-Object - how to access inheritance

At the moment, I try to understand the Javascript prototype object. 目前,我尝试了解Javascript原型对象。 Following situation: 以下情况:

// new Person object
function Person () {
    this.greeth = function() {
        console.log("Good morning, " + this.name);
    };
};

// add new function to Person.prototype for inheritance
Person.prototype.sayWeight = function() {
    console.log(this.weight);
};

// create new friend object
var friend = {
    forename: "Bill",
    lastname: "Gates",
    weight: 78,
    sayhello: function() {
        console.dir("Hello " + this.forename + ' ' + this.lastname);
    }
};

// assign Person.prototype to friend.prototye (inheritance)
friend.prototype = Person;

console.dir(friend);

Now my question: I assign the Person Object to my friend.prototype . 现在我的问题是:我将Person对象分配给我的friend.prototype For my understanding, " friend " should have all the functions of Person.prototype (ie sayWeight() cause of friend.prototype = Person; ). 就我的理解而言,“ friend ”应该具有Person.prototype所有功能(即sayWeight()原因是friend.prototype = Person; )。 But the only function I can call is friend.sayhello. 但是我唯一可以调用的功能是friend.sayhello。 In my output ( console.dir(friend); ), I can see the sayWeight() function, but when I call it, I get an error ( TypeError: Object #<Object> has no method 'sayWeight' ) 在我的输出中( console.dir(friend); ),我可以看到sayWeight()函数,但是当我调用它时,我得到了一个错误( TypeError: Object #<Object> has no method 'sayWeight'

Can you explain this behavior? 你能解释这种行为吗? Why can't I access the sayWeight() function? 为什么不能访问sayWeight()函数?

========================================================= ================================================== =======

Another question: 另一个问题:

function Person() {
    this.name = "Bill Gates";
    this.weight = 78;
    this.sayHello = function() {
        console.log("Hello " + this.name);
    }
}

Person.prototype.sayWeight = function() {
    console.log(this.weight);
}

var friend = new Person();

What is the difference between the sayWeight and the sayHello function? sayWeightsayHello函数之间有什么区别? The sayWeight function is in the prototype-object of Person - okay, but what advantages do I have from prototype in this case? sayWeight函数位于Person的原型对象中-好的,但是在这种情况下,我可以从原型中获得什么好处?

Can you explain this behavior? 你能解释这种行为吗? Why can't I access the sayWeight() function? 为什么不能访问sayWeight()函数?

Because you can't change the prototype of an object after you create it. 因为创建对象后无法更改其原型。 You are setting the prototype property, but the internal prototype reference that is used by the javascript interpreter, namely __proto__ is still the one used in effect, and currently __proto__ is referring to Object.prototype . 您正在设置prototype属性,但是javascript解释器使用的内部原型引用(即__proto__ )仍然有效,当前__proto__引用的是Object.prototype

If you changed this line friend.prototype = Person; 如果您更改此行, friend.prototype = Person; to this one friend.__proto__ = Person.prototype; friend.__proto__ = Person.prototype; then everything will work. 然后一切都会正常。

If your browser supports ES5 then you can use Object.create() to create objects that inherit from a given prototype, or you can use a workaround adopted from the book Javascript: The Good Parts, and twisted a little by David Flanagan in his book: Javascript The Definitive Guide: 如果您的浏览器支持ES5,则可以使用Object.create()创建从给定原型继承的对象,或者可以使用Javascript:The Good Parts一书中的变通方法,并在David Flanagan的书中稍作改动:Javascript权威指南:

// inherit() returns a newly created object that inherits properties from the
// prototype object p. It uses the ECMAScript 5 function Object.create() if
// it is defined, and otherwise falls back to an older technique.
function inherit(p) {
    if (p == null) throw TypeError(); // p must be a non-null object
    if (Object.create) // If Object.create() is defined...
        return Object.create(p); // then just use it.
    var t = typeof p; // Otherwise do some more type checking
    if (t !== "object" && t !== "function") throw TypeError();
    function f() {}; // Define a dummy constructor function.
    f.prototype = p; // Set its prototype property to p.
    return new f(); // Use f() to create an "heir" of p.
}

NOTE __proto__ isn't a standardized property and shouldn't be used in production code, or as @alex noted in his comment it is on the way of standardization. 注意 __proto__不是标准化的属性,不应在生产代码中使用,或者正如@alex在其评论中指出的那样,这是标准化的方式。

NOTE 2: As @thg435 mentioned in his comment, an alternative to using the __proto__ property is using Object.setPrototypeOf() which is standardized in ES6. 注意2:正如@ thg435在他的评论中提到的,使用__proto__属性的另一种方法是使用ES.6中标准化的Object.setPrototypeOf()

EDIT TO COVER LAST QUESTION 编辑以覆盖最后一个问题

What is the difference between the sayWeight and the sayHello function ? sayWeight和sayHello函数之间有什么区别?

The difference is that now each new instance of Person (for example new Person() ) will have a distinct sayHello() function, but a shared sayWeight() function. 区别在于,现在每个新的Person实例(例如new Person()将具有不同的sayHello()函数,但具有共享的sayWeight()函数。

var friend = new Person();
var anotherFriend = new Person();

console.log(friend.sayHello === anotherFriend.sayHello); // OUTPUTS FALSE
console.log(friend.sayWeight === anotherFriend.sayWeight); // OUTPUTS TRUE

what advantages do I have from prototype in this case? 在这种情况下,我从原型有什么优势?

Well less memory, code reuse across all instances of person, and if you already have one or more person objects and you want to add a new method to all of them without modifying each one in turn then you can add that method to the prototype and they will all inherit from it. 更少的内存,代码可以在人员的所有实例之间重用,并且如果您已经有一个或多个人员对象,并且想要向所有对象添加新方法而又不依次修改每个对象,则可以将该方法添加到原型中他们都会从中继承。

Person doesn't inherit Person.prototype , only instances of Person do. Person不继承Person.prototype ,仅继承Person实例。 Further, with a normal Object say foo = {} , foo.prototype is just a normal property. 此外,使用普通对象foo = {}foo.prototype只是普通属性。 You'd either need a constructor or to create the initial object defining it as having a specific prototype. 您将需要构造函数或创建将其定义为具有特定原型的初始对象。

What you actually want is 你真正想要的是

friend = Object.create(Person.prototype);
// or, for older browsers
friend = new Person();
// or some Object.create shim
/* which gives you
friend inherits Person.prototype
       inherits Object.prototype */

This sets up the prototype chain. 这样就建立了原型链。 If you want to create many friends, it may be better to set up a new constructor Friend , which has Friend.prototype = Object.create(Person.prototype); 如果要创建很多朋友,最好设置一个新的构造函数 Friend ,它的Friend.prototype = Object.create(Person.prototype); . This also protects Person.prototype from if you want to add properties to Friend.prototype . 这也保护Person.prototype距离,如果你想添加属性Friend.prototype Then you would have 那你就会有

(instanceof) Friend inherits Friend.prototype
                    inherits Person.prototype
                    inherits Object.prototype

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

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