类 及其继承

81 阅读4分钟

1. 简单的类

new Person():使用 new 关键字调用 Person 构造函数,创建一个新的对象实例。

function Person() {
    this.age = 18;
    this.name = 'xxl';
}
var p = new Person()
alert(p.name)     // xxl

new 关键字执行以下操作: 创建一个新对象。 将新对象的原型设置为构造函数的 prototype 属性。 执行构造函数,并将 this 绑定到新对象上。 如果构造函数返回一个对象,则返回该对象;否则,返回新创建的对象。 var p = ...:将新创建的对象实例赋值给变量 p

2. 给构造函数内部和原型上添加属性和方法

原型链上面的属性会被多个实例调用,构造函数内部的属性不会被多个实例调用

function Person() {
    this.age = 18;
    this.name = 'xxl';
    this.run = function() {
        console.log(this.name + '在运动', 1111)
    }
}
// 【原型链上面的属性会被多个实例调用,构造函数内部的属性不会被多个实例调用】
Person.sex = '女'
Person.prototype.work = function() {
    console.log(this.name + '在工作')   // xxl在工作
}
var p = new Person()
p.work()

3. 给类添加静态方法

类上面添加静态方法,可以直接进行调用不用通过实例化出来的实例进行调用

function Person() {
    this.age = 18;
    this.name = 'xxl';
    // 这里表示的是实例方法,需要 new 出来才可以调用
    this.run = function() {
        console.log(this.name + '在运动', 1111)
    }
}
// 直接给类 添加静态方法
Person.getInfo = function() {
    console.log('信息')    //信息
}
// 静态方法不用实例化,直接调用就行
Person.getInfo()

4. ES5 里的继承

4-1:通过对象冒充实现继承

通过对象冒充实现继承【对象冒充可以继承构造函数内部的属性和方法, 但是对象冒充无法继承原型链身上的属性和方法 】

function Person() {
    this.age = 18;
    this.name = 'xxl';
    this.run = function() {
        console.log(this.name + '在运动', 1111)
    }
}

Person.prototype.work = function() {
    console.log(this.name + '在工作')   // xxl在工作
}
Person.prototype.grade = '一等级'


function Web() {
    // 通过对象冒充实现继承
    Person.call(this)
}
let w = new Web()
// 对象冒充可以继承构造函数内部的属性和方法
console.log(w.age) // 18
w.run()// xxl在运动
// 但是对象冒充无法继承原型链身上的属性和方法
console.log(w.grade)   // undefined
w.work() //  w.work is not a function

4-2:通过原型链来继承

通过原型链来继承【当构造函数内部的参数值是固定的时候,原型链继承是可以实现构造函数和原型链上的属性和方法继承的】 如例子1:
通过原型链来继承,当参数是动态化的话,原型链继承出来的子类的属性就会报 undefined 如例子2

例子1

构造函数内部的参数值是固定的时候,原型链继承是可以实现构造函数和原型链上的属性和方法继承的

function Person() {
    this.age = 18;
    this.name = 'xxl';
    this.run = function() {
        console.log(this.name + '在运动', 1111)
    }
}

Person.prototype.work = function() {
    console.log(this.name + '在工作')   // xxl在工作
}
Person.prototype.grade = '一等级'


function Web() {
    
}
Web.prototype = new Person()
let w = new Web()
// 对象冒充可以继承构造函数内部的属性和方法
console.log(w.age) // 18
w.run()// xxl在运动
// 但是对象冒充无法继承原型链身上的属性和方法
console.log(w.grade)   // 一等级
w.work() //  xxl在工作

例子2

通过原型链继承,当参数是动态化的话,原型链继承出来的子类的属性就会报 undefined

function Person(name, age ) {
    this.age = age;
    this.name = name;
    this.run = function() {
        console.log(this.name + '在运动', 1111)  // undefined在运动
    }
}

Person.prototype.work = function() {
    console.log(this.name + '在工作')   //undefined在工作
}
Person.prototype.grade = '一等级'


function Web(name, age) {
    
}
Web.prototype = new Person()
let w = new Web('gg', 6)       // 实例化子类的时候没法给父类传参
console.log(w.age) // undefined
w.run()
w.work() 

4-3:继承:通过原型链+对象冒充的形式来继承

通过对象冒充的形式来继承:可以继承构造函数内部的属性和方法,实例化子类的时候可以给父类传参

function Person(name, age ) {
    this.age = age;
    this.name = name;
    this.run = function() {
        console.log(this.name + '在运动', 1111)  // gg在运动
    }
}

Person.prototype.work = function() {
    console.log(this.name + '在工作')   //gg在工作
}
Person.prototype.grade = '一等级'


function Web(name, age) {
    Person.call(this, name, age)// 通过对象冒充的形式来继承:可以继承构造函数内部的属性和方法,实例化子类的时候可以给父类传参
}
Web.prototype = new Person()
let w = new Web('gg', 6)       // 实例化子类的时候没法给父类传参
console.log(w.age) // 6
w.run()
w.work() 

4-4:继承:通过原型链+对象冒充的形式来继承的另外一种写法

function Person(name, age ) {
    this.age = age;
    this.name = name;
    this.run = function() {
        console.log(this.name + '在运动', 1111)  // xl在运动
    }
}

Person.prototype.work = function() {
    console.log(this.name + '在工作')   //xl在工作
}
Person.prototype.grade = '一等级'


function Web(name, age) {
    Person.call(this, name, age)// 通过对象冒充的形式来继承:可以继承构造函数内部的属性和方法,实例化子类的时候可以给父类传参
}
Web.prototype =  Person.prototype;
let w = new Web('xl', 18)       // 实例化子类的时候没法给父类传参
console.log(w.age) // 18
w.run()
w.work()

4-5: 4-4 和 4-5 的区别

4-4 原型链继承是Web.prototype = new Person()这种写法,4-5 原型链继承是Web.prototype = Person.prototype; 这种写法,两种写法都可以,都是继承原型链身上的属性和方法。