Recently, I read the series of “Heavy Learning front” written by Winter God, and it was really written by the big guy. I feel that I am not only relearning the front end, but also learning a methodology. This article is a summary of the prototype/prototype chain, starting with the realities of life and tackling some of the most difficult parts of JavaScript to understand.

What is object orientation?

Limited by the Chinese translation, I always thought that “object” was just a concept born for programming. At that time in college, the teacher’s catchphrase was “No object, you have a new one”. However, heisei was about to pass, but I was still solo in my mother’s womb.

Teacher Winter gave the following examples to illustrate the object.

The concept of objects was formed in early childhood, long before the concepts of values, procedures and so on that are commonly used in our programming logic.

In infancy, we always first to realize an apple to eat (where one apple is an object), and then realize all apple can eat (and all of the apple, here is a class), and then we can realize the connection between the three apples and pears, and produces the concept of digital “3” (value).

So, object-oriented programming emphasizes that data and the behavior of manipulating data are intrinsically related, so good design encapsulates data and the behavior associated with it.

For example, a string of characters used to represent a word or phrase is often called a string. Characters are data. But you tend not to care about what the data is, but what you can do with it, so the behavior you can apply to that data (calculating length, adding data, searching, and so on) is designed as a String class method.

Object characteristics of JavaScript

  • Objects are uniquely identifiable: even if two objects are exactly the same, they are not the same object.

  • Stateful: Objects have states. the same object may be in different states.

  • An object has behavior: that is, the state of the object may change because of its behavior.

The first point is easy to understand. Objects are stored in heap memory and have a uniquely identified memory address, so they have a unique identity. Objects have state and behavior. Different ways to call a function make this point different at runtime, resulting in different behavior.

The constructor

A constructor is itself a function, no different from a normal function. But for the sake of distinction, the function that generates an instance using new is called a constructor (formally we usually capitalize the constructor name), and the function that calls it directly is a normal function.

Unlike traditional object-oriented languages, JavaScript has no concept of classes, and even the addition of the class keyword in ES6 is nothing more than syntactic sugar for prototypes. JavaScript also added the new operator to mimic Java, but it was directly followed by a constructor instead of a class.

function Dog(name, age) {
  this.name = name;
  this.age = age;
  this.bark = function() {
    return 'wangwang~';
  };
}

const husky = new Dog('Lolita'.2);
const alaska = new Dog('Roland'.3);
Copy the code

While the code above has an object-oriented flavor, it has one flaw. We created two instances based on Dog, resulting in the Bark method being created twice, which was definitely wasteful. So is there a way to put the Bark method in a single place that all instances can access? Yeah, that’s the prototype we’re going to talk about.

The prototype

Below is a god map where the essence of the archetype/archetype chain is merged. Many interviewers ask you to draw a prototype chain by hand, which is a good reference point.

Archetypes in life

What is a “prototype”? From the perceptual point of view, the prototype is the product of natural human thinking. There is an idiom, “imitate the cat and draw a tiger.” Here the cat is the prototype of the tiger, as is another saying, “Imitate a gourd and draw a gourd.” It can be seen that a “prototype” can be a concrete, existing thing.

And then we look at the class. Take houses and drawings, where drawings are “classes.” The meaning of the drawings is to “guide” the workers to create a real house (example). Therefore, “kind” tends to be a guiding theory and thought.

So JavaScript is the language that really deserves to be called “object-oriented” because it’s one of the few languages that can create objects without using classes.

Technical prototypes

In JavaScript, every function has a prototype property (this is a loose term, as Symbol and Math do not) that points to an object, called a prototype object, that when you create an instance using a constructor, The prototype object pointed to by the prototype property becomes the prototype object of the instance.

By default, the stereotype object has a constructor property that points to the corresponding constructor for the stereotype object. Since the instance object can inherit properties from the stereotype, the instance object can also call the constructor property directly, again pointing to the corresponding constructor of the stereotype object.

function Foo() {}

const foo = new Foo();

// The constructor property of the prototype object points to the constructor
Foo.prototype.constructor === Foo; // true

// The instance's constructor property also points to the constructor
foo.constructor === Foo; // true
Copy the code

Each instance has a hidden attribute [[prototype]] that points to its prototype object, and we can use either of the following two methods to get the instance’s prototype object.

instance.__proto__;

Object.getPrototypeOf(instance);
Copy the code

Note: Prior to ES5, in order to access [[Prototype]], the browser manufacturer created the __proto__ attribute. But after ES5 there are standard methods object.getProtoTypeof and Object.setProtoTypeof. Although the __proto__ attribute has been added to the ES6 specification for browser compatibility, it is no longer recommended.

That’s the end of the prototype, which isn’t really that complicated. From the above picture, we can easily obtain the following formula.

Object.getProtoTypeof (instance) === constructor. Prototype;Copy the code

Therefore, the stereotype object is like a “bridge” between the instance and the constructor, so we can put common properties or methods in the stereotype object, which can solve the problem of constructor instantiation producing multiple duplicate methods. Let’s modify the constructor example and put the Bark method in the Dog constructor prototype so that no matter how many new instances we have, we’ll only create one bark method.

function Dog(name, age) {
  this.name = name;
  this.age = age;
}

Dog.prototype.bark = function() {
  return 'wangwang~';
};

const husky = new Dog('Lolita'.2);
const alaska = new Dog('Roland'.3);

husky.bark(); // 'wangwang~'
alaska.bark(); // 'wangwang~'
Copy the code

Prototype chain

Each object has a prototype object that points to the previous prototype via a __proto__ pointer, inheriting methods and properties from it, and the prototype object may also have a prototype, layer by layer, and so on, until it points to NULL (NULL has no prototype). This relationship is called the Prototype chain, through which one object has properties and methods defined in other objects.

function Parent(name) {
  this.name = name;
}

const p = new Parent();

p.__proto__ === Parent.prototype; // true
p.__proto__.__proto__ === Object.prototype; // true
p.__proto__.__proto__.__proto__ === null; // true
Copy the code

Something about the prototype/prototype chain

Here’s a quick list of common built-in methods for prototype/prototype chains. I recently wrote a series called JavaScript API Full Analysis. For more details, you can go there, or click on the title of each method below.

Object.create()

Used to create a new object that uses the existing object as the __proto__ of the new object. The first argument is a prototype object. The second argument is optional. You can pass in a property descriptor object or null.

That’s right, that’s copy the cat!

const cat = { type: The 'cat' };

const tiger = Object.create(cat);

tiger.tooth = 'teeth';
Copy the code

Object.getOwnPropertyNames()

This method returns an array of all the property names of the specified object’s own properties.

  • Includes non-enumerable properties

  • It does not include the Symbol value as the attribute of the name

  • No properties on the prototype chain are retrieved

  • Returns an empty array if no ordinary string exists as an attribute of the name

// It only gets its own attributes and doesn't care about the attributes on the prototype chain
Object.getOwnPropertyNames(tiger); // ['tooth']
Copy the code

Object.getPrototypeOf() / Object.setPrototypeOf()

These two are used to get and set the prototype of an object, which is mainly used instead of __proto__.

hasOwnProperty

Returns a Boolean value to determine whether an object itself contains this property.

  • All properties on the stereotype chain return false

  • Properties of type Symbol can also be detected

tiger.hasOwnProperty('tooth'); // true
tiger.hasOwnProperty('type'); // false
Copy the code

isPrototypeOf

This method checks if an object exists on another object’s prototype chain and returns a Boolean value.

cat.isPrototypeOf(tiger); // true
Copy the code

The last

Stay tuned for the next article that highlights inheritance and the new classes in ES6.

Welcome to follow my wechat public number: the front of the attack

reference

JavaScript Advanced Programming (3rd edition) by Nicholas C. Zakas

Deep Understanding of ES6 by Nicholas C. Zakas

JavaScript You Don’t Know (Volume 1) by Kyle Simpson

JavaScript prototypes and prototype chains in three minutes

Reconceptualizing constructors, stereotypes, and stereotype chains

[Advanced 5-2] Illustrates prototype chains and their inheritance

Detail JS prototype chain and inheritance