跳到主要内容

类的创建和继承

类的创建(es5):new 一个 function,在这个 function 的 prototype 里面增加属性和方法。

对象创建的方式有哪些?

在 JavaScript 中,对象可以通过以下几种方式进行创建:

  1. 对象字面量(Object Literal): 使用花括号 {} 来定义一个对象,可以在花括号中添加属性和方法。

    const obj = { 
    property1: value1,
    property2: value2,
    method: function() {
    // 方法的定义
    }
    };
  2. 构造函数(Constructor): 使用构造函数创建对象,通过 new 关键字调用构造函数,并使用 this 关键字在构造函数中定义属性和方法。

    function Person(name, age) {
    this.name = name;
    this.age = age;
    this.sayHello = function() {
    console.log(`Hello, my name is ${this.name}`);
    };
    }
    const person = new Person('John', 30);
  3. Object.create() 方法: 使用 Object.create() 方法创建一个新对象,以指定的原型对象作为新对象的原型。

    const prototypeObj = { 
    property1: value1,
    property2: value2,
    method: function() {
    // 方法的定义
    }
    };
    const newObj = Object.create(prototypeObj);
  4. 类(Class): 在 ES6 以后,JavaScript 引入了类(class)的概念,可以使用 class 关键字定义一个类,然后使用 new 关键字创建该类的实例对象。

    class Person {
    constructor(name, age) {
    this.name = name;
    this.age = age;
    }
    sayHello() {
    console.log(`Hello, my name is ${this.name}`);
    }
    }
    const person = new Person('John', 30);
  5. 工厂函数(Factory Function): 使用一个函数来返回一个新的对象,该函数被称为工厂函数,通过调用该函数可以创建多个类似的对象。

    function createPerson(name, age) {
    return {
    name: name,
    age: age,
    sayHello: function() {
    console.log(`Hello, my name is ${this.name}`);
    }
    };
    }
    const person = createPerson('John', 30);

以上是常用的对象创建方式,每种方式都有自己的特点和适用场景。根据实际需求,选择合适的方式来创建对象。

类的继承

  1. 类的继承——原型链继承
function Cat(){ }
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true

缺陷:当通过cat修改引用类型的属性时候,会污染原型链上的属性,影响到所有实例。也不能多继承。

cat.sleep = function() {
console.log('cat 修改了这个方法');
}

var cat2 = new Cat();
console.log(cat.sleep()); // cat 修改了这个方法
  1. 构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给 子类(没用到原型)
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特点:可以实现多继承 缺点:只能继承父类实例的属性和方法,不能继承原型上的属性和方法。

  1. 实例继承和拷贝继承

实例继承:为父类实例添加新特性,作为子类实例返回 拷贝继承:拷贝父类元素上的属性和方法 上述两个实用性不强,不一一举例。

  1. 组合继承:相当于构造继承和原型链继承的组合体。通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true

特点:可以继承实例属性/方法,也可以继承原型属性/方法 缺点:调用了两次父类构造函数,生成了两份实例

  1. 寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
(function(){
// 创建一个没有实例方法的类
var Super = function(){};
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
})();
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

较为推荐

FAQ?

能不能手动实现一下instanceof的功能?

function myInstanceof(left, right) {
//基本数据类型直接返回false
if(typeof left !== 'object' || left === null) return false;
//getProtypeOf是Object对象自带的一个方法,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left);
while(true) {
//查找到尽头,还没找到
if(proto == null) return false;
//找到相同的原型对象
if(proto == right.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
}