原型链和继承

172 阅读1分钟

一、概念

1.构造函数constructor

当我们需要反复创建多个相同属性,可复用的方法的对象的时候,可通过构造函数创建对象

function Person(name,age) {
    this.name = name;
    this.age = age;
    
}
const obj = new Person("xiaoyang","18");
console.log(obj.name,obj.age);  // xiaoyang 18
console.log(obj.constructor === Person);  // true

instanceof 验证对象的是某个构造函数的实例

console.log(obj instanceof Person); // true

2. - 实例方法和原型对象上的方法

实例可以使用构造函数的实例对象、方法和原型属性、方法

function Person(name,age) {
    this.name = name;
    this.age = age;
    // 实例方法
    this.getName = function() {
        return this.name
    }
}
// 原型属性
Person.prototype.limitAge = "20";
// 原型方法
Person.prototype.intruduce = function() {
    console.log(`my name is ${this.name},I am ${this.age}.`)
}
const obj = new Person("xiaoyang","18");
console.log(obj.limitAge);
obj.getName();  // xiaoyang
obj.intruduce();   // my name is xiaoyang,I am 18.

隐式原型__proto__和原型对象prototype

js创造对象时,除了null,所有对象都会有一个__proto__,用于指向构造函数的prototype, 只有函数才有prototype

obj.proto === Person.prototype

image.png

面试题,通过构造函数创建实例的时候,new都做了什么?

const obj = new Person("xiaoyang","18");
  • 创建一个空对象{} const obj = {}
  • 使obj.__proto__ = Person.prototype
  • 调用构造函数,this指向new的新函数, Person.call(p,"xiaoyang","18")
  • 返回新对象的地址
const per = {};
per.__proto__ = Person.prototype;
Person.call(per,'xiaohong',"20");
per.intruduce();   //my name is xiaohong,I am 20.

二、继承

1.冒充对象继承

只能继承实例属性和方法,不能继承原型对象的属性和方法

function Father(firstName,name,age) {
    this.firstName = firstName || 'zhang'; 
    this.name = name;
    this.age = age;
    this.getFullName = function() {
        return firstName+ name;
    }
}
Father.prototype.LimitAge = 18;
Father.prototype.getAge = function() {
    return `I am ${this.age}.`;
}

function Child(firstName,name,age){
    // 主要代码
    Father.call(this,firstName, name, age)
}

const child = new Child("zhang",'san',18)
child.getFullName()  // zhangsan
child.LimitAge    //undefined
child.getAge()    // child.getAge is not a function

child.proto === Child.prototype 但是Child.prototype未继承Father.Prototype

2.原型链继承

function Father(firstName,name,age) {
    this.firstName = firstName || 'zhang'; 
    this.name = name;
    this.age = age;
    this.getFullName = function() {
        return firstName+ name;
    }
}
Father.prototype.LimitAge = 18;
Father.prototype.getAge = function() {
    return `I am ${this.age}.`;
}


function Child(firstName,name,age){
    // 主要代码
    Father.call(this,firstName, name, age)
}
// 主要代码(两种方式)
// Child.prototype = Father.prototype;
// Child.prototype = new Father();

const child = new Child("zhang",'san',18)
child.getFullName()  // zhangsan
child.LimitAge    // 18
child.getAge()    // i am 18.