自学内容网 自学内容网

【js进阶】ES5原生JS中的几种继承方式

在 JavaScript 中,new 关键字主要用于创建一个对象实例,其具体执行的操作如下:

创建一个空对象:首先,会创建一个空的简单 JavaScript 对象,这个对象会继承自构造函数的 prototype 属性。

设置原型链:将新创建的对象的 proto 属性(在现代 JavaScript 中可以使用 Object.getPrototypeOf() 来访问)设置为构造函数的 prototype 属性,从而实现原型链的继承。

绑定 this:将新创建的对象作为 this 的上下文,也就是将构造函数内部的 this 指向这个新对象。

执行构造函数:调用构造函数,将新对象作为 this 传入,执行构造函数内部的代码,对新对象进行属性的添加和初始化等操作。

返回新对象:如果构造函数没有显式返回一个对象,那么会自动返回这个新创建的对象;如果构造函数显式返回了一个对象,那么会返回该对象,而不是新创建的对象。

类式继承

function Person(name) {
  this.name = name;
}
Person.prototype.getName = function () {
  return this.name;
};

const reader = new Person('reader');
console.log(reader.getName()); // reader

function Author(name, book) {
  Person.call(this, name);
  this.book = book;
}

Author.prototype = new Person();
console.log('🚀 ~ Author.prototype:', Author.prototype.constructor);
Author.prototype.constructor = Author;
Author.prototype.getBook = function () {
  return this.book;
};

模拟extend

function extend(subClass, superClass) {
  // 声明一个空的临时中间类构造函数
  var F = function () {};
  // 继承父类的原型方法到中间类构造函数的原型中
  F.prototype = superClass.prototype;
  // 类似继承一个中间类,继承父类的原型方法
  subClass.prototype = new F();
  subClass.prototype.constructor = subClass;
}

function Animal(name, gender) {
  this.name = name;
  this.gender = gender;
}
Animal.prototype.getAge = function () {
  return this.age;
};

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

extend(Dog, Animal);

const dog = new Dog('dog', 10, 'male');
console.log(dog);
console.log(dog.getAge());

在这里插入图片描述

弱化父子类中间的耦合

  • 改进版的extend方法
    子类中无需硬编码Person父类了,只需要用子类自己的属性Dog.superClass.constructor.call(this, ...arguments);
function extend(subClass, superClass) {
  // 声明一个空的临时中间类构造函数
  var F = function () {};
  // 继承父类的原型方法到中间类构造函数的原型中
  F.prototype = superClass.prototype;
  // 类似继承一个中间类,继承父类的原型方法
  subClass.prototype = new F();
  subClass.prototype.constructor = subClass;

  // 弱化对父类的引用,避免不必要的耦合
  subClass.superClass = superClass.prototype;
  if (superClass.prototype.constructor == Object.prototype.constructor) {
    superClass.prototype.constructor = superClass;
  }
}

function Animal(name, gender) {
  this.name = name;
  this.gender = gender;
}
Animal.prototype.getAge = function () {
  return this.age;
};

function Dog(name, age, gender) {
  Dog.superClass.constructor.call(this, ...arguments);
  this.age = age;
  this.gender = gender;
}

extend(Dog, Animal);

const dog = new Dog('dog', 10, 'male');
console.log(dog);
console.log(dog.getAge());

在这里插入图片描述

原型继承

  • 不同于类似继承,无需构造函数
let Person = {
  name: 'default name',
  getName() {
    return this.name;
  },
};

let reader = clone(Person);
console.log(reader.getName());
reader.name = 'reader name';
console.log(reader.getName());

function clone(objec) {
  let F = function () {};
  F.prototype = objec;
  return new F();
}

let Author = clone(Person);
Author.books = [];
Author.hobbies = [];

Author.getBooks = function () {
  return this.books;
};

let author = [];
author[0] = clone(Author);
author[0].name = 'author name';
author[0].books = ['设计模式'];
author[1] = clone(Author);
author[1].name = 'rose harmes';
author[1].books = ['设计模式'];

console.log(author[1].getName());
console.log(author[1].getBooks());

let anthorClone = clone(Author);
console.log(anthorClone.name);

anthorClone.name = 'new name';
console.log(anthorClone.name);

anthorClone.books.push('new book');
anthorClone.hobbies = ['reading', 'writing'];
console.log('🚀 ~ anthorClone.hobbies:', anthorClone.hobbies);
console.log(anthorClone.books, '9090');
let anthorClone2 = clone(Author);
console.log(anthorClone2.books, '8080');
console.log('🚀 ~ anthorClone2.hobbies:', anthorClone2.hobbies);

在这里插入图片描述

  • 修改对象深层次深层次属性的方法
let computedObj = {
  name: '张三',
  usreInfo: {
    age: 18,
    sex: '男',
  },
};

// bad: 直接修改对象
computedObj.usreInfo.age = 20;

// better
computedObj.usreInfo = {
  age: 20,
  sex: '男',
};

// best
let compoundObject = {};

compoundObject.name = '张三';
compoundObject.createUserInfo = function () {
  return {
    age: 100,
    sex: '男',
  };
};
computedObj.usreInfo = compoundObject.createUserInfo();

let compoundObjectClone = clone(compoundObject);
compoundObjectClone.usreInfo = compoundObject.createUserInfo();
compoundObjectClone.usreInfo.age = 20;
  • 参元类,扩展属性

let Mixin = function () {};

Mixin.prototype = {
  serialize() {
    let output = [];
    for (let key in this) {
      output.push(key + '=' + this[key]);
    }
    return output.join('&');
  },
};

function aument(receive, give) {
  for (let property in give) {
    if (!receive.hasOwnProperty(property)) {
      receive[property] = give[property];
    }
  }
}

// 进阶版
function aument2(receive, give) {
  if (arguments[2]) {
    for (let index = 2; index < arguments.length; index++) {
      const element = arguments[index];
      receive.property[element] = give[element];
    }
  } else {
    aument(receive, give);
  }
}

原文地址:https://blog.csdn.net/qq_27702739/article/details/145162261

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!