JS Fundamentals: A Prototype-Based Object System

Introduction:

  Only from the point of view of design patterns, if we want to create an object, one way is to first specify its type, and then create the object through this class, such as traditional object-oriented programming languages ​​"C++", "Java", etc.; Another way is that we don't need to care about the specific type of the object, but find an object and clone it to create an exact same object, like all vampire stories necessarily have a vampire ancestor, in the "Javascript" world" Object" object is this vampire ancestor, all other objects are inherited from "Object" object, if A object inherits from B object, then B object is the prototype of A object.

In a prototype-based object system, at least the following rules are included:

(1) Everything is an object

(2) To create an object not by instantiating the class, but by finding an object as a prototype and cloning it

(3) The object remembers its prototype

(4) If an object cannot respond to a request, it delegates the request to its own prototype (prototype chain)

Create object:

  There are three ways to create objects in JS: through object literals, through constructors, and through the Object.create() function.

//Example 1: Create an object from an object literal 
var boy = {
  name: 'Bob',
  sex: 'male'
}
// Example 2: Create an object through a constructor 
function Person(name, sex) {
   this .name = name;
   this .sex = sex;
}
var boy = new Person('Bob', 'male');
// Example 3: Create an object through the Object.create() function 
var boy1 = {
  name: 'Bob',
  sex: 'male'
}
var boy2 = Object.create(boy1);

everything is an object

  In fact, not everything is an object in JS, this is just a general statement, since JS introduces two data types: primitive types (Undefind, Null, Boolean, Number and String) and object types (Object, Function), Needless to say, the object type is an object. The question is, is the basic type an object? Let's start with the string type to explain:

var str = 'Make life better';
console.log(str.length);         // output 16

It stands to reason that the "str" ​​variable is just a string, but it uses the "length" attribute that only objects have to output the length of the string, so here we have reason to regard the string type as an object, called "wrapper object" ". This object is temporary, that is to say, JS will create the string into a string object through new String() only when its properties are read. Once the reference ends, the object will be destroyed, in other words In other words, the properties of the "wrapper object" are "read only, not write". Similarly, "Boolean" and "Number" can also create their own wrapper objects through their own constructors when reading properties, and refer to their respective properties like objects.

Secondly, "null" means "null value", and the "typeof" operation is performed on "null", and the output result is "Object", so we can also regard "null" as an object, called "null object"

Finally, "unfind" means "undefined". When we only declare a variable without initialization, output "unfind", or refer to a property that does not exist, the output is also "unfind", and execute "typeof" on "unfind" The output of the operation is "unfind", so "unfind" does not actually belong to the object category

To create an object not by instantiating the class, but find an object as a prototype and clone it

  In JS, "Object.prototype" is the prototype of all objects, and we don't need to care about the details of cloning, because that's what the engine is responsible for. All we need to do is to explicitly call var obj1 = {}; or var obj2 = new Object(). At this time, the engine will clone an object from "Object.prototype" as the prototype of the new object.

Example one:

var obj1 = {};
var obj2 = new Object();
console.log(Object.getPrototypeOf(obj1) === Object.prototype); //输出true
console.log(obj2.__proto__ === Object.prototype); //输出true

Each object has a "__proto__" (two underscores before and after) property, which points to the prototype of the object, but it is only an internal property, not a formal external API, which in principle cannot be accessed, this is due to a lot of browsing The support of the device only exposes this property. In ES5, use " Object.getPrototypeOf ()" to get the prototype of an object, and in ES6, you can use " Object.setPrototypeOf()" to set the prototype of an object. So, here the role of both is the same, both get the prototype of the object, and their prototypes are both "Object.prototype".

Only functions have a "prototype" property, such as " Object.prototype ". For a function, the "__proto__" property points to its prototype, and the "prototype" property is the prototype of the object constructed by this function, which can be understood as this A prototype chain, "__proto__" always points to the top of the prototype chain, and the function can just extend the prototype chain, so it pushes the object pointed to by its "prototype" property to the top of the prototype chain, and naturally the "__proto__" of the object it constructs " property points to its own "prototype".

Example two:

function Person(name, sex) {
  this.name = name;
  this.sex = sex;
}
var boy = new Person('Bob', 'male');
console.log(Object.getPrototypeOf(Person) === Function.prototype); //true
console.log(Object.getPrototypeOf(boy) === Person.prototype); //true

The Person function inherits from the Function object, which is straightforward to write like this:

var Person = new Function('name', 'sex', 'this.name = name;this.sex = sex;');

Therefore, the prototype of the Person function points to Function.prototype, and the boy object is constructed through the Person function, so its prototype points to Person.prototype.

Object remembers its prototype

  As mentioned above, JS provides a " __proto__ " property for all objects to access its prototype

If an object cannot respond to a request, it delegates the request to its own prototype

Example:

function A() {}
A.prototype = { name: 'better' };
var a = new A();
a.name = 'bett';
function B() {}
B.prototype = a;
var b = new B();
console.log(b.name); // output bett

The b object itself does not have a "name" property, so it is found in its prototype, that is, the " prototype " of the constructor. The a object has a "name" property, so it stops the traceback and outputs bett.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325297175&siteId=291194637