yxfanxiao / yxfanxiao.github.io

My Blog Space
3 stars 0 forks source link

JS: prototype & __proto__ , 实现类与继承 #9

Open yxfanxiao opened 8 years ago

yxfanxiao commented 8 years ago

__proto__被markdown解析成加粗的 "proto" 了

JavaScript中的prototype

Prototype is a property belonging only to functions. Used in case the function happens to be used as a constructor. You assign properties to a constructor's prototype if you would like them to be inherited by its instances; rather than directly assigned, which saves memory.

JS中,prototype是函数的属性。被用于函数作为构造器的场景。当你想让构造器的properties都被它的实例继承,应该把这些properties赋予构造器的prototype,而不是直接assign,可以节约一点内存。

先实现类:

    // 这个是组合继承(原型链+构造函数)
    function Foo(bar) {
        this.bar = bar
    }
    Foo.prototype.showBar = function() {
        console.log(this.bar)
    }
    // var f = new Foo(222)
    // f.showBar()                  // 222
    // new 约等价于
    var f = {}
    f.__proto__ = Foo.prototype
    Foo.call(f, 22)
    f.showBar()                     // 22

apply/call就第二个参数的不同。apply的实现:

Function.prototype.apply = function(obj, arr) {
    obj = obj || window;
    obj._tem = this;
    var result;
    if (!arr) {
        result = obj._tem();
    } else {
        var args = [];
        for (var i = 0, len = arr.length; i < len; i ++) {
            args.push('arr[' + i + ']');
        }
        result = eval('obj._tem(' + args + ')')
    }
    delete obj._tem;
    return result;
}

原型链:__proto__ 每个对象都内置proto属性,是用来寻找原型链的。

    Function instanceof Object // true`

函数也是Object,所以

    function Foo() {}
    Foo.__proto__.constructor === Function // true
    var f = new Foo()
    f.__proto__ === Foo.prototype // true, f的__proto指向Foo的原型对象
    f.__proto__.constructor === Foo  // true
    Foo.prototype.constructor === Foo // true,Foo的原型对象的构造器是Foo

理解了以上的,再来想一下原型链。当你调用对象a的方法时,若没有在a中找到,则去a的proto对象(也就是a的构造器A的prototype)中寻找,a ---> A ---> 逐级寻找 --->Object.prototype,最后是Object构造函数的原型对象。

接下来是继承:

    function Foo() {}
    function Bar() {}
    Bar.prototype = new Foo()
    Bar.prototype.constructor = Bar

这样,Bar的prototype指向的对象里

- constructor: Bar
- __proto__: Foo (是new Foo()出来的一个实例,相当于把Bar.prototype.__proto__ = Foo.prototype,然后执行Foo.call(Bar))

利用prototype实现了继承~~~

最后的总(tu)结(cao)

ES2015中有了class、extends关键字,写个类终于不用这么麻烦了。但是为什么面试的时候,还要问这些JS的糟粕呢???