javascript 面向对象编程(封装、继承)

在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称”实例”)共有的属性和方法。
Javascript语言不支持”类”,但是可以构造函数的方法,模拟出”类”。

  • 构造函数
    构造函数就是一个普通的函数,但内部使用了this变量,对构造函数使用 new 运算符就能声称事例,并且this变量会帮定在实例对象上。
function Cat(name,color){
    this.name = name;
    this.color = color;
}

//每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
//共有属性和方法可以直接定义在prototype上,指向同一个内存地址
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){
    alert("小猫爱吃鱼");
}

var cat1 = new Cat("小白","white");
var cat2 = new Cat("小黑","black");

alert(cat1.eat == cat2.eat); //true
  • Prototype模式的验证方法
    • isPrototypeOf() : 用于判断某个prototype对象和某个实例之间的关系
    alert(Cat.isPrototypeOf(cat1))   //true
    alert(Cat.isPrototypeOf(cat2))   //true
    • hasOwnPrototype :每个实例化对象都有一个hasOwnPrototype()方法,用于判断某个属性是实例对象属性还是pototype对象属性
    alert(cat1.hasOwnPrototype("name"))   //true
    alert(cat1.hasOwnPrototype("type"))   //false
    • in运算符
      用于查看某个实例是否为某个对象的属性,不管是实例对象属性还是原型对象的属性
    alert("name" in cat1)   //true
    alert("type" in cat1)   //true
运算符还可以用来遍历某个对象的所有属性
    for(var prop in cat1) { alert("cat1["+prop+"]="+cat1[prop]); }
  • 利用空对象作为中介的构造函数的继承
  function Animal(){ }
    Animal.prototype.species = "动物";
    
    function Cat(name,color){
    this.name = name;
    this.color = color;
  }
  //使猫继承于动物  封装成inherits()
    function inherits(Child, Parent) {
        var F = function () {};
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        Child.prototype.constructor = Child;
    }

    //使用该方法
    inherits(Cat,Animal);
    var cat1 = new Cat("大白","whiteMax");
    alert(cat1.species)  //动物
  • class继承

    • 从ES6开始关键字class被引入javascript中,目的:让定义类更简单
    • 比较:JavaScript的对象模型是基于原型实现的,特点是简单,缺点是理解起来比传统的类-实例模型要困难,最大的缺点是继承的实现需要编写大量代码,并且需要正确实现原型链。
  • class类定义

class Cat{
    constructor(name,color){
        this.name = name;
        this.color = color;
    };
    eat(){
        alert("小猫爱吃鱼")
    }
}
//实例化 
var cat1 = new Cat("小白","white");
var cat2 = new Cat("小黑","black");

console.log(cat1.eat === cat2.eat)   //true
console.log(cat1.name === cat2.name)  //false
console.log(Cat.isPrototypeOf(cat1))  //false  //不是通过原型对象创建的
  • class继承
    class Animal{
      constructor(name){
        this.name = name;
        this.species = "动物"
      }
    }

    class Cat extends Animal{
      constructor(name,color){
        super(name);   //继承父类的constructor(name)
        this.color = color;
      }

      hello(){
        return "Hello, "+this.name +"!";
      }
    }

    var cat1  = new Cat("小白","white");
    var cat2 = new Cat("小黑","black");

    console.log(new Cat('x') instanceof Animal)    //true
    console.log(cat1.species)  //动物   -->  证明Cat继承Animal类
    console.log(cat1.hello() === cat2.hello());  //false
    • extends则表示原型链对象来自Animal。子类的构造函数可能会与父类不太相同,例如,Cat需要name和color两个参数,并且需要通过super(name)来调用父类的构造函数,否则父类的name属性无法正常初始化。

    • Cat已经自动获得了父类Animal的species属性,我们又在子类中定义了新的hello()方法。

    • ES6引入的class和原有的JavaScript原型继承实际上它们没有任何区别,class的作用就是让JavaScript引擎去实现原来需要我们自己编写的原型链代码。简而言之,用class的好处就是极大地简化了原型链代码。

    需要一个工具把class代码转换为传统的prototype代码,可以试试Babel这个工具。

    • 参考链接

Javascript 面向对象编程(一):封装

Javascript面向对象编程(二):构造函数的继承

Javascript面向对象编程(三):非构造函数的继承

原型继承

Class 继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值