Prototype and prototype chain
Each constructor has a prototype object, which contains a pointer to the constructor, and instances contain internal Pointers to the prototype object.
person.__proto__ === Person.prototype
Copy the code
Each stereotype has a constructor property pointing to the associated constructor
Person.prototype.constructor === Person
Copy the code
Es5 gets the prototype of the object
Object.getPrototypeOf(person) === Person.prototype
Copy the code
inheritance
Prototype chain
- Basic idea: Use stereotypes to make arrays and methods of one reference type inherit from another.
- Disadvantages: Advantages are also disadvantages of stereotype chain inheritance. The stereotype properties of a reference class are shared by all instances, and arguments cannot be passed to the parent type
Function Animal(){this.species = [' husky ',' husky ']} function Dog(){} prototype = new Animal(); Var dog1 = new Dog(); Dog1.species. Push (' samoyed ') var dog2 = new Dog(); console.log(dog1.species); / / / "husky", "corgi", "samoyeds]" the console. The log (dog2. Species); // [" husky ", "corgi "," Samoyed "]Copy the code
Borrow constructor inheritance
- Basic idea: Call the supertype constructor inside the subtype constructor
- Advantages: One big advantage of borrowing constructors over stereotype chains is that subtype function constructors can pass arguments to supertype constructors
- Disadvantages: Methods are defined in constructors, so function reusability is out of the question.
function Animal(){
this.species = ['Husky'.'corgi']}function Dog(){
Animal.call(this)}var dog1 = new Dog();
dog1.species.push(samoya)
var dog2 = new Dog();
console.log(dog1.species); // [" husky ", "corgi "," Samoyed "]
console.log(dog2.species); // [" husky ", "corgi "]
Copy the code
Passing parameters
function Animal(speices){
this.speices = speices;
}
function Dog(speices){
Animal.call(this,speices);
}
var dog1 = new Dog('Chinese Rural Dog');
var dog2 = new Dog();
console.log(dog1.speices); // Chinese farm dog
console.log(dog2.speices); // Chinese farm dog
Copy the code
Combination of inheritance
- Basic idea: Stereotype chain implements inheritance of stereotype properties and methods, while borrowing constructors implements inheritance of instance properties
- Advantages: Defining methods on prototypes enables function reuse while occasionally ensuring that each instance has its own attributes
- Cons: In any case, the supertype constructor is called twice (for what reason, more on that later)
function Animal(speices){
this.speices = speices;
this.skills = ["jump"."climb"."catch"."run"]
}
Animal.prototype.getSpeices = function(){
console.log(this.speices)
}
function Dog(speices,color){
// use the constructor to inherit the attributes of the parent class
Animal.call(this,speices); / / the second time
this.color = color;
}
// Prototype inheritance inherits the methods of the parent class
Dog.prototype = new Animal(); / / for the first time
Dog.prototype.getColors = function(){
console.log(this.colors);
}
var dog1 = new Dog('leung'.'white'); // When used here
dog1.skills.push('acting');
console.log(dog.skills); // ["jump","climb","catch","run","acting"]
dog1.getSpeices(); / / commanding,
var dog2 = new Dog('corgi'.'brown');
console.log(dog2.skills); // ["jump","climb","catch","run"]
dog2.getSpeices(); / / corgi
Copy the code
Let’s draw a picture of the two calls to the parent constructor
When the Animal constructor is called for the first time, dog. prototype gets two properties, speices and Skills, in the Dog prototype. When the Dog constructor is called, the Animal constructor is called again, this time on the new instance object. Instance properties speices and Skills are created on the new object, which mask the two properties with the same name in the stereotype
Primary inheritance
- Basic idea: Without using constructors, prototypes allow you to create new objects based on existing objects without having to create custom types. is
ES5 Object.create
A mock implementation that uses the incoming object as a prototype for the object being created. - Advantages: To keep one object similar to another, there is no need to create a constructor
- Disadvantages: Values containing reference types are always shared, as is the drawback of stereotype chain inheritance
function createObj(o){
function F(){}
F.prototype = o;
return new F();
}
Copy the code
use
var dog = {
species: 'Bichon Frise'.color: 'gold'.skills: ["jump"]}vardog1 = createObj(dog);// The dog object is the basis of the dog1 object, which in ES5 can be written here
dog1.species = 'teddy';
dog1.color = 'brown';
dog1.skills.push('acting');
vardog2 = createObj(dog); dog2.species =chihuahua;
dog2.color = 'grey';
dog2.skills.push('show');
console.log(dog1.skills) // ["jump","acting","show"]
console.log(dog2.skills) // ["jump","acting","show"]
Copy the code
The original type inheritance is written as objecte.createes5, which also has a second argument of the same format as the second argument to the object.defineProperties () method, for example
var person = {
name: "Southern blue".age: 24.hobby: ['acting'.'codeing; ] } Object.create(person,{ })Copy the code
var o
o = {};
// An empty object created literally is equivalent to:
o = Object.create(Object.prototype);
Copy the code
Parasitic inheritance
- Basic idea: Closely related to primitive inheritance, create a function that encapsulates the inheritance process
- Advantages: Parasitic inheritance can also be effective when considering objects that are not custom types and constructors
- Disadvantages: Using parasitic inheritance to add functions to objects, function reuse cannot be achieved
function createDog(obj){
var clone = Object.create(obj);
clone.getColor = function(){
console.log(clone.color)
}
return clone
}
var dog = {
species: poodle.color: 'yellow'
}
var dog1 = createDog(dog);
dog1.getColor(); // yellow
Copy the code
Parasitic combinatorial inheritance
Basic idea: inherit properties using borrowed constructors, and inherit methods using hybrid forms of stereotype chains. It’s similar to combinatorial inheritance, but it solves the problem of combinatorial inheritance calling the parent’s constructor twice, making a change when the subclass’s prototype calls the parent’s constructor, and using parasitic inheritance to do this, we want nothing more than a copy of the parent’s prototype
Advantages: Solves the problem of combining inheriting the constructor of the parent class twice, which is generally considered the most desirable approach
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function inheritPrototype(child,parent){
var prototype = object(parent.prototype); Object. Create (parent. Prototype)
prototype.constructor = child; // enhance the image
child.prototype = prototype; // Specify the object
}
function Animal(speices){
this.speices = speices;
this.skills = ["jump"."climb"."catch"."run"];
}
Animal.prototype.getSpeices = function(){
console.log(this.speices)
}
function Dog(species,color){
Animal.call(this,species);
this.color = color;
}
inheritPrototype(Dog,Animal);
// Dog. Prototype = new Animal()
var dog1 = new Dog('Sheepdog'.'black');
dog1.getSpeices(); / / shepherd
Copy the code
Issues involved: Carefully compare combinatorial inheritance (borrowing constructor inheritance + archetypal inheritance) with parasitic combinatorial inheritance (borrowing constructor and archetypal chain mixing)
The class keyword
Instance attributes
class Person {
constructor(name) {
this.name = name; // Instance properties
}
sayHello() {
return 'hello, I am ' + this.name; }}var kevin = new Person('Kevin');
kevin.sayHello()
Copy the code
new
class Person {
name = "Both"
sayHello() {
return 'hello, I am '+ name; }}Copy the code
Corresponding ES5 code
function Person(){
this.name = name
}
Person.prototype.sayHello = function() {
return 'hello, I am ' + this.name;
}
Copy the code
Static properties and methods
All methods or methods defined in a class are inherited by the instance. If you prefix a method with the static keyword, it means that the method or property is not inherited by the instance, but is called directly from the class. This is called a “static method or property”.
class Person {
static name = "xiaoju"
static sayHello = function(){
return 'hello, I am '+ name; }}console.log(Person.name)
Person.sayHello()
Copy the code
Corresponding ES5 code
function Person() {}
Person.sayHello = function() {
return 'hello';
};
Person.sayHello(); // 'hello'
var kevin = new Person();
kevin.sayHello(); // TypeError: kevin.sayHello is not a function
Copy the code
class Person {
constructor(){
this.age = 24
}
static bar = 'bar';
static onSayHello = function(){
return this.bar
}
sayHello() {
return 'hello, I am ' + this.age; }}Copy the code
Corresponding ES5 code
function Person(){
this.age = 24
}
Person.prototype.sayHello = function(){
retur 'hello,I am' + this.age
}
Person.bar = "bar"
Person.onSayHello = function(){
return this.bar
}
Copy the code
Compiled code
"use strict";
function _instanceof(left, right) { if(right ! =null && typeof Symbol! = ="undefined" && right[Symbol.hasInstance]) { return!!!!! right[Symbol.hasInstance](left); } else { return left instanceofright; }}function _classCallCheck(instance, Constructor) { if(! _instanceof(instance, Constructor)) {throw new TypeError("Cannot call a class as a function"); }}function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); }}function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true.configurable: true.writable: true }); } else { obj[key] = value; } return obj; }
var Person = /*#__PURE__*/function () {
function Person() {
_classCallCheck(this, Person);
this.age = 24;
}
_createClass(Person, [{
key: "sayHello".value: function sayHello() {
return 'hello, I am ' + this.age; }}]);returnPerson; } (); _defineProperty(Person,"bar".'bar');
_defineProperty(Person, "onSayHello".function () {
return this.bar;
});
Copy the code
The class inheritance
ES6 extends. Constructor must call the superclass’s constructor with the super keyword, otherwise the subclass cannot be instantiated because it does not have its own this object. Super () is equivalent to parent.call (this)
ES6 code
class Parent {
constructor(name) {
this.name = name;
}
getName (){
return this.name
}
}
class Child extends Parent {
constructor(name, age) {
super(name); // Call parent class constructor(name)
this.age = age; }}var child1 = new Child('kevin'.'18');
console.log(child1);
Copy the code
The __proto__ attribute of a subclass
console.log(Child.__proto__ === Parent)
console.log(Child.prototype.__proto__ === Prarent.prototype)
Copy the code
ES5 code
function Parent (name) {
this.name = name;
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child (name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child
var child1 = new Child('kevin'.'18');
console.log(child1);
Copy the code
The principle of the call
Function.prototype.myCall = function (context) {
var context = context || window;
context.fn = this;
var args =[...arguments].slice(1);
varresult = context.fn(... args)delete context.fn
return result;
}
Copy the code
Apply the principle of
Function.prototype.myApply = function (context) { context = context ? context : window context.fn = this let args = [...arguments][1] if (! args) { return context.fn() } let result = context.fn(... args) delete context.fn; return result }Copy the code
The bind to realize
Function.prototype.bind2 = function (context) {
if (typeof this! = ="function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.slice.call(arguments.1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
Copy the code
The principle of the new
function objectFactory() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
return typeof ret === 'object' ? ret : obj;
};
Copy the code
reference
Github.com/mqyqingfeng… Github.com/mqyqingfeng…
Js Advanced Programming Version 3