web前端练习22----js中的原型对象prototype,原型链(重要)

原型对象 原理解析:

我们创建的每一个函数,解析器都会向函数中添加一个属性 prototype
这个属性对应着一个对象,就是原型对象。

如果函数作为普通函数,调用 prototype 没有任何作用

当函数以构造函数的形式调用时,它所创建的对象都会有一个隐含的属性 __proto__,
我们可以通过 __proto__ 来访问原型对象

原型对象就相当于一个公共区域,同一个构造函数的实例都能访问到这个原型对象
我们可以将对象共有的内容,统一设置到原型对象中

创建构造函数时,可以将对象共有的属性和方法,统一添加到构造函数的原型对象中,
这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了

当我们访问对象的一个属性或者方法时,他会先在对象自身中寻找,如果有则直接使用,
如果没有则会去原型对象中寻找,如果有则直接使用。
如果原型对象中也没有,则会在原型对象的原型对象中寻找,一层一层往上找,直到找到Object的原型对象,
如果没有,就没有这个属性或方法

图解:

web前端练习22----js中的原型对象prototype,原型链(重要)_第1张图片

 

下面写一些具体例子:

拿到原型对象:

        // 拿到原型对象:
        function method1() {
            // 构造函数
            function Person() {

            }
            // 原型对象
            let yuanxing = Person.prototype;

            // 实例化对象
            let person1 = new Person();
            // 通过对象找到原型对象 person1.__proto__
            console.log(yuanxing == person1.__proto__);

            // 任何对象都可以找到原型对象 person2.__proto__
            let person2 = new Person();
            console.log(yuanxing == person2.__proto__);

        }

调用对象属性和方法,先在自身找,自身没有在原型对象中找

        //调用对象属性和方法,先在自身找,自身没有在原型对象中找
        function method2() {
            // 构造函数
            function Person() {

            }

            // 向原型对象中添加属性和方法
            Person.prototype.name = 'zhh';
            Person.prototype.method = function (args) {
                console.log('原型对象的方法>>>' + args);
            }

            // 调用对象属性和方法,先在自身找,自身没有在原型对象中找
            let person1 = new Person();
            let person2 = new Person();

            console.log(person1.name = 'peson1');
            person1.method('person1调用');

            console.log(person2.name = 'perso2');
            person2.method('person2调用');

        }

原型对象也是对象,所以它也有原型(就是原型对象的原型对象)
当我们使用一个对象的属性或方法时,会先在自身找,
自身有,则直接使用
自身没有,则去原型对象中寻找,如果原型对象中有,则使用
如果原型对象中也没有,则去 原型对象的原型对象 中去寻找。
以此类推向上寻找,直到找到Object的原型对象,Object 的原型对象,没有原型对象,
如果依然没找到则返回 unedfined

        function method3() {
            // 构造函数
            function Person() {
               
            }
            let person = new Person();
            // person 对象中没有 toLocaleString() ; 调用的是原型对象中的方法
            person.toLocaleString();

            // 下面查找 toLocaleString() 在哪一级的原型对象里面

            // hasOwnProperty() 对象自身是否含有某个属性或方法
            // person 中是否有 toLocaleString 方法
            console.log(person.hasOwnProperty('toLocaleString'));

            // person的原型对象中是否有 toLocaleString 方法
            console.log(person.__proto__.hasOwnProperty('toLocaleString'));

            // person的原型对象的原型对象中是否有 toLocaleString 方法
            // 打印结果是true
            // 说明person.toLocaleString()调用的是person.__proto__.__proto__中的toLocaleString方法
            console.log(person.__proto__.__proto__.hasOwnProperty('toLocaleString'));
            }

OK,讲完了

下面是一个综合的例子:

    

 

下面对原型对象进行深层次的解析

1、原型对象在堆栈存储

看下面一段代码:

    

上面代码,堆栈是示意图,(很重要,这个图比上面Person示意图要详细)

web前端练习22----js中的原型对象prototype,原型链(重要)_第2张图片

2、构造函数和原型对象的相互指向

构造函数对象的 prototype 属性,指向原型对象
原型对象中的 constructor 指向构造函数对象

看下面一段代码:

    

图解:

web前端练习22----js中的原型对象prototype,原型链(重要)_第3张图片

3、几个重要概念和结论
I、两个概念:
1.显式原型对象  函数对象.prototype
2.隐式原型对象  实例对象.__proto__


II、Function 和Object 的三个重要结论
1、函数的原型对象都是Object的实例(但Object除外)
2、所有的函数对象都是 Function 的实例 (Function 是他自己的实例)
3、Object 的原型对象是原型链的尽头

上面3个结论的验证:

1、函数的原型对象都是Object的实例(但Object除外) 

        /* 
         * 1、函数的原型对象都是Object的实例(但Object除外)   
         */
        // Person的原型对象,是Object 实例
        console.log(Person.prototype instanceof Object);
        // Object的原型对象不是Object 实例
        console.log(Object.prototype instanceof Object);
        // Function的原型对象,是 Object 实例
        console.log(Function.prototype instanceof Object);

2所有的函数对象都是 Function 的实例 (Function 是他自己的实例)

/* 
         * 2所有的函数对象都是 Function 的实例 (Function 是他自己的实例)
         */

        {
            //  例如:Dog函数对象,内部就是 new Function()得到的
            //        所以 Dog 就是 Function 的实例
            function Dog() {

            }
            //  实例化对象
            let dog = new Dog();
            //  对象中添加方法
            dog.method = function() {
                console.log('对象中添加方法');
            }
            dog.method();
        }


        {
            // 上面的代码可以写成这样
            //  Dog是构造函数对象
            let Dog = new Function();
            //  实例化对象
            let dog = new Dog();
            //  对象中添加方法
            dog.method = function() {
                console.log('对象中添加的方法2');
            }
            dog.method();
        }

        // Function是自己的实例
        // Function.prototype 的Function是函数对象
        // Function.__proto__ 的Function是实例对象
        console.log(Function.prototype == Function.__proto__);

3.Object 的原型对象是原型链的尽头

        /* 
         * 3.Object 的原型对象是原型链的尽头
         */
        console.log(Object.prototype.__proto__);

根据上面的三条结论验证 instanceof  判断时原型链的指向

例子1:

    // 案例1
    function Foo() {

    }
    let foo = new Foo();
    console.log(foo instanceof Foo);
    console.log(foo instanceof Object);

console.log(foo instanceof Foo); 结果是true,示意图如下:

web前端练习22----js中的原型对象prototype,原型链(重要)_第4张图片

console.log(foo instanceof Object);结果true,示意图如下:

web前端练习22----js中的原型对象prototype,原型链(重要)_第5张图片

例子2

    // 案例2
    console.log(Object instanceof Function);
    console.log(Object instanceof Object);
    console.log(Function instanceof Function);
    console.log(Function instanceof Object);

    function Fooo(){}
    console.log(Object instanceof Fooo);

console.log(Object instanceof Function); 结果true,示意图如下:

web前端练习22----js中的原型对象prototype,原型链(重要)_第6张图片

console.log(Object instanceof Object);结果是true,示意图如下:

web前端练习22----js中的原型对象prototype,原型链(重要)_第7张图片

console.log(Function instanceof Function);结果是true,示意图如下:

web前端练习22----js中的原型对象prototype,原型链(重要)_第8张图片

console.log(Function instanceof Object);结果是true,示意图如下:

web前端练习22----js中的原型对象prototype,原型链(重要)_第9张图片

    function Fooo(){}

    console.log(Object instanceof Fooo);结果是 false 结果如下:

web前端练习22----js中的原型对象prototype,原型链(重要)_第10张图片

OK,原型对象全部讲完了

参考视频

http://www.gulixueyuan.com/my/course/58

http://www.gulixueyuan.com/course/194

js继承机制的设计思想

http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html

 

 

 

 

 

 

 

 

你可能感兴趣的:(web前端2018)