• JavaScript 原型


    /*
     * JavaScript 中,对象分为普通对象和函数对象,Object 和 Function 是JS自带的函数对象。
     * 函数对象的一个属性是原型对象 prototype,普通对象没有prototype。
     * 原型对象其实就是普通对象(Function.prototype除外,它是函数对象,但它很特殊,它没有prototype属性)。
     * 在函数对象创建的时候,创建了一个它的实例对象并赋值给它的prototype,即函数对象的原型对象就是自己的一个实例对象。(凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。Function.prototype = new Function (); 所以Function.prototype是函数对象。
     * 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype,函数对象的原型对象的__proto__属性,它指向创建它的函数对象Object的原型对象prototype。Object.prototype对象也有__proto__属性,但它比较特殊,为null。这个有__proto__串起来的直到Object.prototype.__proto__为null的链叫做原型链。
     * Object.__proto__ === Function.prototype 
     * Object是函数对象,是通过new Function()创建,所以Object.__proto__指向Function.prototype。
     * Function.__proto__ === Function.prototype
     * Function也是对象函数,也是通过new Function()创建,所以Function.__proto__指向Function.prototype。
     * Function.prototype.__proto__ === Object.prototype
     * 原型对象中都有个预定义的constructor属性,用来引用它的函数对象。
     * Function.prototype.constructor === Function
     * Object.prototype.constructor === Object
     * Object.constructor===Function 本身Object就是Function函数构造出来的。
     */
    
    // 工厂模式创建对象
    function createObject(name, age) {
        // 1.创建对象
        var obj = new Object();
        // 2.添加实例属性
        obj.name = name;
        obj.age = age;
        // 3.添加实例方法
        obj.run = function() {
            return this.name + this.age;
        };
        return obj;
    }
    var myBox = createObject("Lee", 28);
    var myBoxBox = createObject("Leeee", 288);
    myBox.run(); // "Lee28"
    myBoxBox.run(); // "Leeee288"
    
    // 构造函数创建对象
    function Box(name, age) {
        this.name = name;
        this.age = age;
        this.run = function() {
            return this.name + this.age;
        };
    }
    var myBox = new Box("Lee", 28);
    myBox.run(); // "Lee28"
    
    // call() 对象冒充 定义对象o冒充Box 对象o便具备Box的属性和方法
    var o = new Object();
    Box.call(o, "Lee", 28);
    o.run(); // "Lee28"
    
    // 把构造函数中的方法通过全局函数来实现引用地址相等 但是破坏了封装性 不推荐
    function Box(name, age) {
        this.name = name;
        this.age = age;
        this.run = run;
    }
    function run() {
        return this.name + this.age;
    }
    var myBox1 = new Box("Lee", 28);
    var myBox2 = new Box("Leeeee", 2888);
    myBox1.run(); // "Lee28"
    myBox2.run(); // "Leeeee2888"
    myBox1.run == myBox2.run; // true
    
    // 原型
    // 定义(构造函数)对象 Box
    /* 
     * 定义 Box 的默认操作
     * 创建一个临时普通对象 即为 Box 的原型对象 var temp = new Box();
     * 为 Box 定义属性 prototype 指向 Box 的原型对象 Box.prototype = temp;
     * 为 Box.prototype 对象定义 constructor 属性 该属性指向构造函数即 Box 对象 Box.prototype.constructor = Box;
     * 为 Box.prototype 对象定义 __proto__ 属性 该属性指向创建它的 Object 对象的原型对象 Box.prototype.__proto__ = Object.prototype;
     */
    function Box(name, age) {
        this.name = name;
        this.age = age;
        this.run = function() {
            return this.name + this.age;
        }
    }
    typeof Box; // "function"
    typeof Box.prototype; // "object"
    Box.prototype; // Object {constructor: function Box(name, age), __proto__: Object}
    Box.prototype.__proto__ === Object.prototype; // true
    
    // 添加原型属性和方法
    Box.prototype.name = "Lee";
    Box.prototype.age = 28;
    Box.prototype.run = function() {
        return this.name + this.age;
    };
    
    // 定义函数对象 Box 的实例对象 myBox1
    /*
     * 定义函数对象 Box 的实例对象 myBox1 默认操作
     * 为 myBox1 对象定义属性 __proto__ 该属性指向指向创建它的 Box 对象的原型对象 myBox1.__proto__ = Box.prototype;
     * JavaScript 会通过 __proto__ 属性向上寻找所有的属性和方法 所以为 Box.prototype 定义的属性和方法即为 Box 对象的所有实例对象共有属性和方法
     */
    var myBox1 = new Box("Leeeee", 288888);
    myBox1.__proto__; // Object {name: "Lee", age: 28, run: function(), constructor: function Box(name, age), __proto__: Object}
    myBox1.__proto__ === Box.prototype; // true
    myBox1.run(); // "Leeeee288888"
    myBox1.__proto__.run(); // "Lee28"
    myBox1.constructor; // 见下
    /*
    function Box(name, age){
        this.name = name;
        this.age = age;
        this.run = function() {
            return this.name + this.age;
        }
    }
    */
    // 原型对象.isPrototypeOf(实例对象) 判定实例对象是不是指向了原型对象
    Box.prototype.isPrototypeOf(myBox1); // true
    
    var  myBox2 = new Object();
    Box.prototype.isPrototypeOf(myBox2); // false
    
    // 删除实例属性
    myBox1.name; // "Leeeee"
    delete myBox1.name; // true
    // myBox1.name 属性不存在 通过 __proto__ 属性寻找到 Box.prototype.name 属性
    myBox1.name; // "Lee"
    
    // 判断实例属性中是否存在指定属性
    myBox1.hasOwnProperty("name"); // false
    
    // 删除原型属性
    delete Box.prototype.name; // true
    myBox1.name; // undefined
    // 判断实例属性或者原型属性中是否存在指定属性
    "name" in myBox1; // false
    
    // 重定义或者覆盖属性
    Box.prototype.name = "KK";
    myBox1.name; // "KK"
    "name" in myBox1; // true
    
    // 遍历原型对象所有的属性和方法
    var num = 0;
    for (o in Box.prototype) {
        console.log(o); // 依次输出见下
        num++;
    }
    /*
    age
    run
    name
    */
    
    // 遍历实例对象和原型对象所有的属性和方法
    var num = 0;
    for (o in myBox1) {
        console.log(o + ":" + myBox1[o]); // 依次输出见下
        num++;
    }
    /*
    age:288888
    run:function () {
            return this.name + this.age;
        }
    name:KK
    */
    
    // 使用字面量的方式创建原型对象
    // 字面量创建原型对象 constructor 属性指向 Object
    Box.prototype = {
        name: "lucy",
        age: 10,
        run: function() {
            return this.name + this.age;
        }
    }
    var myBox = new Box("lucy", 12);
    myBox1.constructor; // 见下
    /*
    function Box(name, age){
        this.name = name;
        this.age = age;
        this.run = function() {
            return this.name + this.age;
        }
    }
    */
    myBox.constructor; // function Object() { [native code] }
    myBox.constructor === Box; // false
    myBox.constructor === Object; // true
    
    // 使用字面量创建原型对象 并且把 constructor 指向 Box
    Box.prototype = {
        constructor: Box,
        name: "Lily",
        age: 10,
        run: function() {
            return this.name + this.age;
        }
    };
    var myBox = new Box();
    myBox.constructor; // 见下
    /*
    function Box(name, age){
        this.name = name;
        this.age = age;
        this.run = function() {
            return this.name + this.age;
        }
    }
    */
    // Box.prototype 重写会切断实例与原来原型的关系
    myBox1.__proto__.run(); // "KK28"
    myBox.__proto__.run(); // "Lily10"
    
    // 查看 Array 原型对象里的方法 sort()
    Array.prototype.sort; // function sort() { [native code] }
    
    // 给 String 原型对象添加方法 addString()
    String.prototype.addString; // undefined
    String.prototype.addString = function() {
        return this + "被添加了!";
    }
    var box = "Lee";
    box.addString(); // "Lee被添加了!"
    var box = new String("Lee");
    box.addString(); // "Lee被添加了!"
    
    // 组合构造函数和原型模式
    // 保持独立用的构造函数
    function Box(name, age) {
        this.name = name;
        this.age = age;
        this.family = ['哥哥', '姐姐'];
    }
    // 保持共享用的原型
    Box.prototype = {
        constructor: Box,
        run: function() {
            return this.name + this.age;
        }
    }
    var box = new Box("pu", 28);
    box.run(); // "pu28"
    
    // 动态原型模式,把原型封装到构造函数里
    // 保持独立用的构造函数
    function Box(name, age) {
        this.name = name;
        this.age = age;
        this.family = ['哥哥', '姐姐'];
        // 原型初始化只有第一次才执行
        if (typeof this.run != 'function') {
            Box.prototype.run = function() {
                return this.name + this.age;
            };
        }
    }
    var box = new Box("pu", 28);
    box.run(); // "pu28"
    
    // 寄生构造函数 = 工厂模式 + 构造函数
    function Box(name, age) {
        var obj = new Object();
        obj.name = name;
        obj.age = age;
        obj.run = function() {
            return this.name + this.age;
        };
        return obj;
    }
    var box = new Box("Lee", 28);
    box.run(); // "Lee28"
    
    // 稳妥构造函数 = 工厂模式
    function Box(name, age) {
        var obj = new Object();
        obj.name = name;
        obj.age = age;
        obj.run = function() {
            return this.name + this.age;
        };
        return obj;
    }
    // 不使用new
    var box = Box("Lee", 28);
    box.run(); // "Lee28
    
    // 继承
    // 通过原型链继承
    function Box() {
        this.name = "Lee"; // L1
    }
    Box.prototype.name = "Jack";
    function Desk() {
        this.age = 100;
    }
    Desk.prototype = new Box();
    var desk = new Desk();
    // 属性寻找采用就近原则,如果L1行没有定义实例属性,打印出原型属性 Jack
    desk.name; // "Lee"
    
    // 使用对象冒充,只能继承构造里的实例属性,不能继承原型属性。
    function Box(name, age) {
        this.name = name;
        this.age = age;
        this.family = ['哥哥', '姐姐', '妹妹'];
    }
    Box.prototype.run = function() {
        return this.name + this.age;
    }
    function Desk(name, age) {
        Box.call(this, name, age)
    }
    var desk = new Desk('Lee', 28);
    
    desk.name; // "Lee"
    desk.family; // ["哥哥", "姐姐", "妹妹"]
    // 出错因为继承不到原型里的方法
    desk.run(); // desk.run is not a function(…)
    
    // 添加原型链继承 称为组合继承
    Desk.prototype = new Box();
    var desk = new Desk('Lee', 28);
    desk.run(); // "Lee28"
    
    // 原型式继承
    // 临时中转函数
    function obj(o) {
        function F() {}
        F.prototype = o;
        return new F();
    }
    
    var box = {
        name: "Lee",
        age: 100,
        family: ['哥哥', '姐姐', '妹妹']
    };
    var myBox = obj(box);
    myBox.name; // "Lee"
    
    // 寄生式继承 = 原型式 + 工厂模式 目的是为了封装函数继承的过程
    function obj(o) {
        function F() {}
        F.prototype = o;
        return new F();
    }
    //寄生函数
    function create(o) {
        var f = obj(o);
        f.run = function() {
            return this.name;
        };
        return f;
    }
    var box = {
        name: "Lee",
        age: 100,
        family: ['哥哥', '姐姐', '妹妹']
    };
    var myBox = create(box);
    myBox.run(); // "Lee"
    
    // 寄生组合函数
    // 临时中转函数
    function obj(o) {
        function F() {}
        F.prototype = o;
        return new F();
    }
    //寄生函数
    function create(box, desk) {
        var f = obj(box.prototype);
        f.constructor = desk; //调整构造指针
        desk.prototype = f;
    }
    function Box(name, age) {
        this.name = name;
        this.age = age;
    }
    Box.prototype.run = function() {
        return this.name + this.age;
    }
    function Desk(name, age) {
        Box.call(this, name, age); //对象冒充
    }
    
    // 通过寄生组合继承来实现继承
    create(Box, Desk);
  • 相关阅读:
    深入理解Azure自动扩展集VMSS(1)
    使用ARM和VMSS创建自动扩展的web集群
    使用ARM模板部署自动扩展的Linux VMSS(2)
    使用ARM模板部署自动扩展的Linux VMSS(1)
    Azure上A/D系列虚拟机到DS系列迁移(2)
    ORM进阶操作
    Django之中间件
    restful十项规范
    同源策略与跨域请求
    Django之CSRF问题
  • 原文地址:https://www.cnblogs.com/pumushan/p/6757070.html
Copyright © 2020-2023  润新知