zoukankan      html  css  js  c++  java
  • js 原型链 prototype __proto__

    1、说明

    函数(Function)才有prototype属性,对象(除Object)拥有__proto__。

    2、prototype与__proto__区别

     

     示例:

    <!DOCTYPE html>
    <html lang="zh">
    
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <meta http-equiv="X-UA-Compatible" content="ie=edge" />
            <title>prototype与__proto__区别</title>
        </head>
    
        <body>
            <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
            <script type="text/javascript">
                var a = {};
                console.log(a.prototype); //undefined
                console.log(a.__proto__); //Object {}
    
                var b = function() {}
                console.log(b.prototype); //b {}
                console.log(b.__proto__); //function() {}
            </script>
        </body>
    
    </html>

    控制台输出:

     

    (3)__proto__指向

    示例:

    <!DOCTYPE html>
    <html lang="zh">
    
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <meta http-equiv="X-UA-Compatible" content="ie=edge" />
            <title>__proto__指向</title>
        </head>
    
        <body>
            <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
            <script type="text/javascript">
                /*1、字面量方式*/
                var a = {};
                console.log(a.__proto__); //Object {}
    
                console.log(a.__proto__ === a.constructor.prototype); //true
    
                /*2、构造器方式*/
                var A = function() {};
                var b = new A();
                console.log(b.__proto__); //A {}
    
                console.log(b.__proto__ === b.constructor.prototype); //true
    
                /*3、Object.create()方式*/
                var a1 = {
                    a: 1
                }
                var a2 = Object.create(a1);
                console.log(a2.__proto__); //Object {a: 1}
    
                console.log(a2.__proto__ === a2.constructor.prototype); //false(此处即为图1中的例外情况)
            </script>
        </body>
    
    </html>

    控制台输出:

    (4)原型链

    (1)是__proto__指向的一条指针链!

    (2)查找属性时,首先先查找自身属性,找不到的话,在查找原型链上的属性。但是不会查找自身的prototype属性。

    示例代码:

    <!DOCTYPE html>
    <html lang="zh">
    
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <meta http-equiv="X-UA-Compatible" content="ie=edge" />
            <title>属性查找</title>
        </head>
    
        <body>
            <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
            <script type="text/javascript">
                Function.prototype.age = 20;
                let b = function() {}
                b.prototype.age = 10;
                console.log(b.age)//输出20
            </script>
        </body>
    
    </html>

     

    示例:

    <!DOCTYPE html>
    <html lang="zh">
    
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <meta http-equiv="X-UA-Compatible" content="ie=edge" />
            <title>原型链</title>
        </head>
    
        <body>
            <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
            <script type="text/javascript">
                var A = function() {};
                var a = new A();
                console.log(a.__proto__); //A {}(即构造器function A 的原型对象)
                console.log(a.__proto__.__proto__); //Object {}(即构造器function Object 的原型对象)
                console.log(a.__proto__.__proto__.__proto__); //null
            </script>
        </body>
    
    </html>

    (5)prototype

    prototypelength是每一个函数类型自带的两个属性,而其它非函数类型并没有,这一点之所以比较容易被忽略或误解,是因为所有类型的构造函数本身也是函数,所以它们自带了prototype属性:

    示例:

    <!DOCTYPE html>
    <html lang="zh">
    
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <meta http-equiv="X-UA-Compatible" content="ie=edge" />
            <title>prototype</title>
        </head>
    
        <body>
            <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
            <script type="text/javascript">
                console.log(Object.prototype); //=> {} 
    
                console.log(Function.prototype); //=> [Function: Empty] 
    
                console.log(String.prototype); //=> [String: '']
            </script>
        </body>
    
    </html>

    除了prototype之外,Js中的所有对象(undefinednull等特殊情况除外)都有一个内置的[[Prototype]]属性,指向它“父类”的prototype,这个内置属性在ECMA标准中并没有给出明确的获取方式,但是许多Js的实现(如Node、大部分浏览器等)都提供了一个__proto__属性来指代这一[[Prototype]],我们通过下面的例子来说明实例中的__proto__是如何指向构造函数的prototype的:

    <!DOCTYPE html>
    <html lang="zh">
    
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <meta http-equiv="X-UA-Compatible" content="ie=edge" />
            <title>prototype与__proto__</title>
        </head>
    
        <body>
            <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
            <script type="text/javascript">
                var Person = function() {};
    
                Person.prototype.type = 'Person';
    
                Person.prototype.maxAge = 100;
    
                var p = new Person();
    
                p.name = 'rainy';
    
                Person.prototype.constructor === Person; //=> true 
    
                p.__proto__ === Person.prototype; //=> true 
    
                console.log(p.prototype); //=> undefined
                console.log(p.maxAge); //100
                console.log(p.__proto__.maxAge); //100
                console.log(p.name); //rainy
                console.log(p.__proto__.name); //undefined
            </script>
        </body>
    
    </html>

    图示:

    Person是一个函数类型的变量,因此自带了prototype属性,prototype指向中的Person.prototype对象。Person.prototype.constructor又指向Person本身;通过new关键字生成的Person类的实例p1,通过__proto__属性指向了Person的原型。这里的__proto__只是为了说明实例p1在内部实现的时候与父类之间存在的关联(指向父类的原型),在实际操作过程中实例可以直接通过.获取父类原型中的属性,从而实现了继承的功能。

    (6)原型链

    示例代码:

    <!DOCTYPE html>
    <html lang="zh">
    
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <meta http-equiv="X-UA-Compatible" content="ie=edge" />
            <title>prototype与__proto__</title>
        </head>
    
        <body>
            <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
            <script type="text/javascript">
                var Obj = function() {};
    
                var o = new Obj();
    
                o.__proto__ === Obj.prototype; //=> true 
    
                o.__proto__.constructor === Obj; //=> true
    
                Obj.__proto__ === Function.prototype; //=> true 
    
                Obj.__proto__.constructor === Function; //=> true
    
                Function.__proto__ === Function.prototype; //=> true 
    
                Object.__proto__ === Object.prototype; //=> false 
    
                Object.__proto__ === Function.prototype; //=> true
    
                Function.__proto__.constructor === Function; //=> true 
    
                Function.__proto__.__proto__; //=> {} 
    
                Function.__proto__.__proto__ === o.__proto__.__proto__; //=> true 
    
                o.__proto__.__proto__.__proto__ === null; //=> true
            </script>
        </body>
    
    </html>

    (7)null与undefined

    null与undefined 无原型

    //报错
                console.log(Object.getPrototypeOf(undefined))
                //报错
                console.log(Object.getPrototypeOf(null))

     

    从上面的例子和图解可以看出,prototype对象也有__proto__属性,向上追溯一直到null

    (8)原型链的遍历过程(一直到null)

     

    <!DOCTYPE html>
    <html lang="zh">
    
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <meta http-equiv="X-UA-Compatible" content="ie=edge" />
            <title>原型链的遍历过程</title>
        </head>
    
        <body>
            <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
            <script type="text/javascript">
                let a = 1
                console.log(a.__proto__ === Number.prototype) //true
                console.log(Number.__proto__ === Function.prototype) //true
                console.log(Function.__proto__ === Function.prototype) //true
                console.log(Function.__proto__.__proto__ === Object.prototype) //true
                console.log(Function.__proto__.__proto__.__proto__)
            </script>
        </body>
    
    </html>

     (9)获取原型对象

    Object.getPrototypeOf(object)

    (10)原型上可遍历的属性

     __proto__ 隐式原型 prototype显示原型

  • 相关阅读:
    jsp——java服务页面
    会话管理——cookie和session技术
    [Java]如何为一个自定义类型的List排序。
    silverlight——获取控件相对位置
    C#操作xml文件
    [转载]Unicode中对中文字符的编码
    silverlight——多次异步调用的顺序执行
    内心需要跟我一起长大
    生活总是问题叠着问题,而任务就是一件问题一件问题的解决~
    真的该学点新的东西了。
  • 原文地址:https://www.cnblogs.com/mengfangui/p/9566114.html
Copyright © 2011-2022 走看看