JS继承/class类

ES5继承

对象上的方法

公有属性/方法

设置给实例对象的属性和方法被称作公有属性和公有方法

私有属性/方法

声明在构造函数中的变量或函数,被称作为私有属性和私有方法

静态属性/方法

js中无需实例化就可以调用的方法或属性叫做静态方法和静态属性

特权方法

在构造函数中给实例对象绑定的方法被称为特权方法

示例

function Car(color,speed){
    // 私有属性
    let num = 0
    // 私有方法
    function fn(){
        console.log("fn")
    }

    // 公有属性---这个属性是设置给所有实例化对象的
    this.color = color
    this.speed = speed

    // 特权方法---在构造函数中给实例化对象设置的方法被称为特权方法
    this.getColor = function(){
        console.log("特权方法")
    }
}


    // 公有方法---这个方法是设置给所有实例化对象的
    Car.prototype.run = function(){
        console.log("驾");
    }

    // 静态属性/静态方法---就是简单的把Car当做一个对象(函数对象),扩展的属性和方法
    Car.title = "造车"
    Car.do = function(){
        console.log("doit");
    }

继承

当一个对象能够使用另一个对象的属性和方法的时候,被称为继承

简单继承

let obj = {
    name:"rolls",
    do:function(){
        console.log("ghost")
    }
}

let obj1 = Object.create(obj)

obj1.name = "G63"

// obj1可以使用obj的属性和方法,称为继承
console.log(obj1,obj)
// { name: 'G63' } { name: 'rolls', do: [Function: do] }
console.log(obj1.name)
// G63

借用构造函数继承

  • 只能继承构造函数中添加的属性和方法
  • 思路
    1.定义父类构造函数
    2.定义子类构造函数
    3.在子类型构造函数中调用父类型构造(call)
// 封装一个父类
function Animal(name,age){
    this.name = name
    this.age = age
}

Animal.prototype.say = function(){
    console.log("吼吼吼")
}


// 封装一个子类
function Cat(color,name,age){
    /* 
        本来Animal的this指向的是Animal的实例对象
        现在让Animal的this指向Cat的实例对象,并且才传参给Animal
    */
   Animal.call(this,name,age)
   this.color = color
}
Cat.prototype.do = function(){
    console.log("玩红外线")
}

let cat1 = new Cat("white","baozi",2)
let cat2 = new Cat("coffce","wanan",3)
console.log(cat1,cat2);
// Cat { name: 'baozi', age: 2, color: 'white' }
// Cat { name: 'wanan', age: 3, color: 'coffce' }

// cat1.say()
// cat2.say()
//  cat1.say is not a function

cat1.test() // 456
cat2.test() // 456

原型链继承

  • 只能继承原型对象上的方法
  • 思路
    1.定义父类型构造函数
    2.给父类型的原型添加方法
    3.定义子类型的构造函数
    4.创建父类型的对象赋值给子类型的原型
    5.将子类型原型的构造函数属性设置为子类型
    6.给子类型原型添加方法
    7.创建子类型的对象:可以调用父类型的方法
    8.子类型的原型为父类型的一个实例对象
function Animal(name, age) {
    this.name = name;
    this.age = age;
}
Animal.prototype.say = function () {
    console.log("吼~")
}


function Cat(color, name, age) {
    this.color = color;
}
/* 
    Cat的实例化对象想要使用Animal的原型对象上的方法,需要修改Cat的原型链
    千万不要把Animal的原型对象直接赋值给Cat的原型对象,否则修改Cat Animal也修改了,因为赋值是地址值的赋值
    Cat.prototype = Animal.prototype;
*/
//再次考虑,还有谁可以访问Animal的原型对象?Animal的实例化对象
//把父类的实例化对象 赋值给 子类的原型对象  此时可以实现原型链继承
Cat.prototype = new Animal();
//如果重新设置了原型对象,那么新的原型对象的constructor就可能出问题
//为了保证程序合理,要把constructor指向修改正确
Cat.prototype.constructor = Cat; //修正constructor
Cat.prototype.do = function () {
    console.log("玩红外线");
}

var cat1 = new Cat("white");
console.log(cat1)
// Cat { color: 'white' }
cat1.say()
// 吼
console.log(cat1.constructor)
// [Function: Cat]
console.log(Cat.prototype.constructor)
// [Function: Cat]

原型链+构造函数继承

function Animal(name, age) {
    this.name = name;
    this.age = age;
}
Animal.prototype.say = function () {
    console.log("吼~")
}


function Cat(color, name, age) {
    this.color = color;
    // 构造函数继承
    Animal.call(this,name,age)
}

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat; 
Cat.prototype.do = function () {
    console.log("玩红外线");
}

var cat1 = new Cat("white","wanan",2);
console.log(cat1)
// Cat { color: 'white', name: 'wanan', age: 2 }
cat1.say()
// 吼
console.log(cat1.constructor)
// [Function: Cat]
console.log(Cat.prototype.constructor)
// [Function: Cat]

ES6 class

class

class Person{
     /* 
        当new的时候,会自动调用constructor这个方法,必须存在(书写公有属性)
        书写在构造函数中的属性 都放在了constructor
     */
    constructor(name,age){
        this.name = name
        this.age  = age
    }

    // 直接书写在class中的方法 其实就是原型对象上的公有方法
    eat(){
        console.log("吃饭")
    }
    // 如果直接在class中书写属性,则还是实例化对象所有的(这样写无法传参)
    sex = "男"

    // static 定义的属性和方法其实都是静态属性和方法 是构造函数上的
    static hi = "hello"
}

// 也可以通过原型对象扩展原型方法
Person.prototype.drink = function(){
    console.log("大乌苏")
}


const p1 = new Person("laowang",20)
const p2 = new Person("xiaowang",10)

console.log(p1,p2)
// Person { sex: '男', name: 'laowang', age: 20 }
// Person { sex: '男', name: 'xiaowang', age: 10 }

console.log(p1.eat === p2.eat)
// true

console.dir(Person)
// [class Person] { hi: 'hello' }

extends

  • ES6中继承的子类中,如果使用构造函数constructor()那么就必须使用super()方法初始化,这样下面才可以调用this关键字。super()只能用在子类的构造函数之中,用在其他地方就会报错,这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。
class Person {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    eat() {
        console.log("吃饭")
    }
    sex = "男"
    static hi = "hello"
}

Person.prototype.drink = function () {
    console.log("大乌苏")
}


// 定义一个Student类 继承 Person类
class Student extends Person {
    constructor(project, name, age) {
        super(name,age)
        this.project = project
    }
    study(){
        console.log("我最喜欢ES6了");
    }
}

const s1 = new Student("nodejs","xiaozhang",19)
console.log(s1)
// Student { sex: '男', name: 'xiaozhang', age: 19, project: 'nodejs' }

s1.eat()
// 吃饭
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值