基础笔记(1)——prototype和__proto__

原型链是JS最难的部分之一,说实话真的有点绕。我之前的思维一直停留在传统的面向对象上,始终转不过弯,网上文章越看越乱。现在算是勉强理解了。记录一下备用。

1、方法和对象

JS中的对象有很多种,说比较常见的两种:
`

    // Object
    let obj = {};

    // Function
    function Foo() {

    }

obj和Foo都是一个对象,唯一有点区别的就是Foo可以加上括号被调用,但是给obj加上括号就是报错了

    obj();
    // Uncaught TypeError: obj is not a function

    Foo();
    // 可以正常被调用

`

2、prototype

所有Function类型的对象都有一个默认的属性就是prototype,但是Object类型的对象(非标准说法)则没有。这是最大的区别。

prototype也是对象,是一个Object类型的对象。

默认创建的prototype有个默认属性就是constructor, constructor指向这个Function类型对象本身。

prototype上的方法可以被所有由这个Function类型对象构造出来的对象调用。

    function Foo() {

    }
    /*
        Foo.prototype = {
            constructor: Foo        
        }
    */

    Foo.prototype.constructor === Foo
    //true

    // Foo、Foo.prototype.constructor是Function类型的对象(其实是一个人)
    // Foo.prototype是Object类型对象,所以没有Foo.prototype.prototype了

    Foo.ptototype.test = function() {
        console.log(111);
    }

    var a = new Foo();

    a.test();
    // 111

prototype称为对象的原型

3、__proto__

这个属性指向了 [[prototype]],但是 [[prototype]] 是内部属性,不能访问。

这个属性所有对象都有,不管他是什么类型。

调用对象方法时,会通过proto依次向上查找,直到找到对应方法。

每个对象的_proto__指向自身构造函数的prototype

    function Foo() {

    }
    var a = new Foo();

    // a是Foo构造出来的,所以:
    // a.__proto__ === Foo.prototype

    // Foo.__proto__ 指向哪?
    // Foo是由Function构造出来的,所以:
    // Foo.__proto__ === Function.prototype

    // Function.__proto__指向哪
    // Function已经是Function类型对象的最顶端了,Function可以理解为自己构造了自己。所以:
    // Function.__proto__ === Function.prototype

    // Foo.prototype.__proto__ 指向哪?
    // Foo.prototype是一个Object类型对象,他是Object构造出来的,所以:
    // Foo.prototype.__proto__ === Object.prototype 

    //  Object.prototype.__proto__指向哪?
    //  Object.prototype是一个Object类型对象,他是Object构造出来的, 那Object.prototype.__proto__ === Object.prototype?,这样有点乱套了。这是个特例
    // Object.prototype.__proto__ === null

    // Object.__proto__ 指向哪?
    // Object是一个Function类型的对象。可以用typeof看看。Object是Function构造出来的。所以:
    // Object.__proto__ === Function.prototype

    // 根据__proto__ 我们可以找到一个对象怎么演变的。
    // Foo.__proto__      Function.prototype
    // Foo.__proto__.__proto__  Object.prototype
    // Foo.__proto__.__proto__.__proto__   null

    // a.__proto__      Foo.prototype
    // a.__proto__.__proto__ Object.prototype 
    // a.__proto__.__proto__.__proto__  null

__proto__ 就是对象的原型链

    function Foo(){

    }
    Foo.prototype.test0 = function() {
        console.log('test0');
    }
    Function.prototype.test1= function() {
        console.log('test1);
    }
    Object.prototype.test2= function() {
        console.log('test2);
    }

    var a = new Foo();

    //调用test0
    a.test0();
    Foo.prototype.test0();

    //调用test1
    Foo.test1();
    Object.test1();
    Function.test1();

    //调用test2
    a.test2();
    Foo.prototype.test2();
    Object.prototype.test2();
    Foo.test2();
    Function.test2();
    Object.test2();

    // 对于test0
    // Foo.test0()是错的

    // 对于test1、test2
    // Function.test1() 和 Object.test2()却是对的, 为什么?
    // Function.__proto__ === Function.prototype, 所以Function.test1()可以
    // Object.__proto__ === Function.prototype
    // Function.prototype.__proto__ === Object.prototype
    // Object.__proto__.__proto__ === Object.prototype
    //所以调用Object.test2()通过两次向上查找,找到test2

好绕啊。

发表评论

电子邮件地址不会被公开。 必填项已用*标注