简体   繁体   中英

How does prototypes and object wrappers work in JavaScript?

I wrote down what I learned in a few sentences to really understand how prototypes and object wrappers work. Please correct me if I'm wrong and let me know if I'm missing additional details.

JavaScript uses prototype to find methods and properties on objects. For example if you create a string "Hello" which is a primitive string value and tries to apply the method split() on it ( "Hello".split() ), string value is coerced to a String object so we can apply the split() method. This String object is created by String.prototype.constructor . After it is created JavaScript looks for the split() method in the prototype object. After the method is applied and the value is returned, the String object is no longer needed, thus it is sacrificed to the Gods of garbage collection.

You're essentially correct, though stack space and inheritance are two different issues, and in a high-level scripting language like js exactly how garbage collection works is probably iffy. It's true though that intermediate values of a single code line would be destroyed after that line completed.

Also, String.prototype.constructor would simply be the same as String itself. Any “instance” of String would receive a .__proto__ reference that would point to String.prototype , creating an inheritance chain. If an object property is found to not be defined an object x itself, JavaScript automatically checks first the object referenced by x.__proto__ , then x.__proto__.__proto__ , all the way up to — in most cases — Object.prototype .

Keep in mind that the __proto__ is implemented differently between JavaScript interpreters, and should not be manually manipulated. It's good to know such a reference exists to explain the prototype magic, but there's no circumstance under which you should be directly changing an object's __proto__ reference. Instead, you should create an instance of a class by either the new operator, or Object.create . A full super/subclass relationship in JavaScript would look like this:

function Animal( name, weight ){
    this.name = name, this.weight = weight;
    this.alive = true;
    this.hungry = true;
}

// At this point you could put in Animal.prototype = Object.create(Object.prototype); but JavaScript will set it automatically, so it’s unnecessary

Animal.prototype.kill = function(){
    this.alive = false;
}

Animal.prototype.feed = function(){
    this.hungry = false;
}

function Cat(name, weight){
    Animal.call(this, name, weight);
    this.lives = 9;
}


// Sometimes people instance a new parent like
// Cat.prototype = new Animal('doesntmatter', 420);
// The result is the same except that using Object.create saves the overhead
// of running a full constructor for an object that doesn’t need it
Cat.prototype = Object.create(Animal.prototype);

Cat.prototype.kill = function(){
    this.lives--;
    if(this.lives <= 0) this.alive = false;
};


var a = new Animal();
var c = new Cat();

/* a.feed and b.feed now reference the same function object,
but c.kill has been overridden since its prototype `__proto__` chain first 
visits Cat.prototype, then Animal.prototype, then Object.prototype. */

Finally, ES6 introduces a class keyword which is syntactical sugar for this system, and abstracts the constructor to an init method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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