• JavaScript笔记——面向对象与原型


    JavaScript也是一门面向对象的语言。面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是,JavaScript竟然没有class,因此它的面向对象也与其他的OOP语言有所不同,创建对象和继承关系都显得很怪异很复杂难用

    创建对象

    JavaScript也采用了构造函数的概念:

    function Box(name, age) {   //构造函数模式
    this.name = name;
    this.age = age;
    this.run = function () {
    return this.name + this.age + '运行中...';
    };
    }
    var box1 = new Box('Lee', 100); 
    var box2 = new Box('Jack', 200);
    alert(box1.run());
    alert(box1 instanceof Box);   //很清晰的识别他从属于 Box

    构造函数的方法有一些规范:

    1.函数名和实例化构造名相同且大写,(非强制,但这么写有助于区分构造函数和普通函数)

    2.通过构造函数创建对象,必须使用 new 运算符(构造函数和普通函数的唯一区别,就是他们调用的方式不同。构造函数也是函 数,必须用 new 运算符来调用,否则就是普通函数了)

    构造函数示意图:

     

    原型的概念

    在创建类之前,先要有原型的概念,我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个对象,它的用途是 包含可以由特定类型的所有实例共享的属性和方法。简单地说原型就是实现共享的功能:比如说类里的方法和一些需要共享的属性(较少见)

    function Box() {}    //声明一个构造函数
    Box.prototype.name = 'Lee';    //在原型里添加属性
    Box.prototype.age = 100;
    Box.prototype.run = function () {    //在原型里添加方法
    return this.name + this.age + '运行中...';
    };
    var box1 = new Box();
    var box2 = new Box();
    alert(box1.run== box2.run);     //true,方法的引用地址保持一致

    在上面的run方法和name,age属性不论声明多少个对象都是相等的(共享了)


    原型示意图:

    在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。__proto__ 属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性 constructor。 通过这两个属性,就可以访问到原型里的属性和方法了。浏览器中无法获取其内部信息

    原型的声明是有先后顺序的,所以,重写的原型会切断之前的原型

    function Box() {};
    
    Box.prototype = { //使用原型创建属性和方法
    constructor : Box,
    name : 'Lee',
    age : 100,
    run : function () {
    return this.name + this.age + '运行中...';
         }
    };
    
    Box.prototype = {      //原型被重写了
    age :200
    };
    var box = new Box(); 
    alert(box.run());     //错误TypeError: box.run is not a function ,因为重写了原型,原来的原型方法,属性失效

    创建类与对象

    使用动态原型模式创建对象可以使方法成为共享的,而属性各是各的

    //动态原型模式创建对象
    function Box(name,age){
        this.name=name;
        this.age=age;
        
        if(typeof this.run!='function'){
            Box.prototype.run=function(){                //使用原型来实现方法共享
                return this.name+this.age+'运行时';
            };
        }
    }
    
    var box1=new Box('lz',21);
    var box2=new Box('Jack',20);
    alert(box1.run());
    alert(box2.run());

    继承

    继承是面向对象中一个比较核心的概念。其他正统面向对象语言都会用两种方式实现继承:一个是接口实现,一个是继承。而JavaScript只支持继承,不支持接口实现

    推荐使用寄生组合继承的方式:

    function obj(o) {           //传递一个字面量函数
    function F() {}             //创建一个构造函数
    F.prototype = o;          //把字面量函数赋值给构造函数的原型
    return new F();          //最终返回出实例化的构造函数
    }
    
    function create(box,desk){                 //将来传入父类和子类
        var f=obj(box.prototype);           //将父类的原型传入
        f.constructor=desk;                    //改变子类的constructor
        desk.prototype=f;                     //又将f传给子类的原型
    }
    
    function Box(name,age){            //父类
        this.name=name;
        this.age=age;
        this.arr=['爸爸','妈妈','儿子'];
        if(typeof this.run!='function'){
            Box.prototype.run=function(){
                return this.name+this.age+'运行时';
            }
        }
    }
    
    function Desk(name,age){                      //子类
        Box.call(this,name,age);                 //对象冒充
    }
    
    create(Box,Desk);                                  //通过这里实现继承
    
    
    //下面是证明不同子类对象互不影响(不同空间)
    var desk=new Desk('lz',21);
    desk.arr.push('女儿');
    alert(desk.arr);
    
    
    var desk2=new Desk('jack',20);
    alert(desk2.arr);
  • 相关阅读:
    【JAVA与C#比较】其它
    C#和java之间的一些差异与共性
    C#与Java的语法差异
    关于npm本地安装模块包(node_modules),安装不了的问题
    vue
    vue
    vue
    vue
    v
    vue -model
  • 原文地址:https://www.cnblogs.com/lz2017/p/6786892.html
Copyright © 2020-2023  润新知