原型链模式-拓展

批量设置原型上的原型和方法
方法一

    var pro = Fn.prototype; // 把原来原型指向的地址赋值给pro,现在他们操作的是同一个内存地址
    pro.getX = function () {
        console.log(this.x);
    }
    pro.getY = function () {

    }
    var f1 = new Fn();

方法二
重构原型对象的方式 -> 自己新开辟一个堆内存,存储公有属性和方法,把浏览器原来给Fn.prototype开辟的那个替换掉。

    function Fn() {
        this.x = 100;
    }
    Fn.prototype = {
        // 手动增加constructor指向:
        constructor: Fn,
        a: function () {

        },
        b: function () {

        },
        c: function () {

        }
    }
    var f = new Fn();
    f.a();
    f.b();
    f.c();
  1. 只有浏览器天生给Fn.prototype开辟的堆内存里面才有constructor,而我们自己开辟的这个堆内存没有这个属性, 这样constructor指向就不再是Fn而是Object了
    console.log(f.constructor); // -> 没做任何处理前,Object
    // 为了和原来的保持一致,需要手动的增加constructor指向
  1. 用这种方式给内置类增加公有的属性
    例如:给内置类Array增加一个数组去重的方法
    Array.prototype.unique = function () {

    }
    Array.prototype = {
        constructor: Array,
        unqiue: function () {
            // 这种方式不行
        }
    }
    console.dir(Array.prototype);

这种方式会把之前存在于原型上的属性和方法替换掉,所以用这种方式修改内置类的话,浏览器是会将其屏蔽的。
但是我们可以一个个的修改内置类的方法,通过下述方式在数组的原型上增加方法,如果方法名和原来内置的重复了,会把内置的方法修改了。 -> 我们以后再内置类的原型上增加方法,命名都需要加特殊的前缀。

    Array.prototype.sort = function () {
        console.log(this); // this -> ary 当前要操作的数组
    }
    var ary = [1, 2, 3, 3, 1, 3, 4, 12];
    ary.sort();

在原型模式中,this常用的有两种情况:
在类中,this.xxx = xxx;this -> 当前类的实例。
某一个方法中的this -> 看执行的时候 "." 前面是谁,this就是谁。

  1. 需要先确定this的指向(即this是谁)。
  2. 把this替换成对应的代码。
  3. 按照原型链查找的机制,一步步的查找结果。
    function Fn() {
        this.x = 100;
        this.y = 200;
        this.getY = function () {
            console.log(this.y);
        }
    }
    Fn.prototype = {
        constructor: Fn,
        y: 300,
        getX: function () {
            console.log(this.x);
        },
        getY: function () {
            console.log(this.y);
        }
    };
    var f = new Fn();
    f.getX(); // -> console.log(f.x) -> 100
    f.__proto__.getX(); // -> this 是f.__protoo_ -> console.log(f.__proto__.x) -> undefined
    Fn.prototype.getX(); // -> this 是Fn.prototype -> Fn.prototype.x -> undefined

    f.getY(); // -> f.y -> 200
    f.__proto__.getY(); // -> this是f.__proto__ -> f.__proto__.y -> 300

在内置类的原型上拓展一个方法,用于数组去重

    Array.prototype.myUnique = function () {
        // this -> ary
        var obj = {};
        for (var i = 0; i < this.length; i++) {
            var cur = this[i];
            if (obj[cur] === cur) {
                this[i] = this[this.length - 1];
                this.length--;
                i--;
                continue;
            }
            obj[cur] = cur;
        }
        obj = null;
        return this; // 目的是为了实现链式写法
    }

链式写法:执行完数组的一个方法,可以紧接着执行下一个方法。
原理:
ary为什么可以使用sort方法? -> 因为sort是Array.prototype上的公有的方法,而数组是ary是Array的一个实例,所以ary可以使用sort方法 -> 只有数组才能使用Array原型上定义的属性和方法。
sort执行完成的返回值是一个排序后的"数组",所以可以继续执行reverse()。
reverse执行完成的返回值也是一个"数组",所以可以继续执行pop()。
pop()执行完成的返回值是被删除的最后一个元素,不是一个数组了,所以在执行数组相关操作会报错。

    ary.sort(function (a, b) {
        return a - b;
    }).reverse().pop();
    ary.myUnique(); // this -> ary
    Array.prototype.myUnique(); // this -> Array.prototype
    console.log(ary);

你可能感兴趣的:(原型链模式-拓展)