原型链介绍

124 阅读3分钟

什么是原型链:

每一个对象都有自己的原型,而原型也是对象,也有自己的原型,一次类推而形成的链式结构就叫做原型链

对象访问原型链中的成员采用就近原则

1.如果自己本身有就去自己的,如果自己没有就从原型中找,如果原型中也没有就从原型的原型中找,一次类推知道找到原型链的终点null,如果还没有找到是属性就返回undefined , 如果是方法就返回xxx is not a function.

js中的对象都是由构造函数创建的

1.自定义构造函数

        function Person(name,age){
            this.name = name;
            this.age = age;
        };

        //每一个人都可以打招呼,可以添加到原型中
        Person.prototype.sayHi = function(){
            console.log('今天六一儿童节,今晚请你洗剪吹');
        };

        //人类属于哺乳动物,可以添加到原型中
        Person.prototype.type = '哺乳动物';

        var p1 = new Person('班长',20);

        console.log(p1);
        
        /*面试题 :请说出下面程序运行的结果
         */
         console.log(p1.name);//班长    p1自己有name属性
         console.log(p1.type);//哺乳动物  p1自己虽然没有type属性,但是它的原型有type
         p1.sayHi();//    p1自己虽然没有sayHi方法,但是它的原型有

        //对象取值:不存在undefined
         console.log(p1.girlFriend);//undefined   p1自己没有girlFriend,原型也没有,
         //p1.eat();//程序报错  eat is not a function    p1自己没有eat方法,原型也没有,

        //为什么不报错? p1自己没有toString  p1的原型也没有toString  但是p1的原型的原型有toString
         console.log(p1.toString());


         //1.查看p1的原型
         console.log(p1.__proto__.constructor);//Person
         console.log(p1.__proto__ === Person.prototype);//true

         //2.查看p1原型的原型
        console.log( p1.__proto__.__proto__.constructor);//Object
        console.log( p1.__proto__.__proto__ === Object.prototype);//true

        //3,查看p1的原型的原型的原型
        console.log(p1.__proto__.__proto__.__proto__);//null

2.查看内置对象的原型链

        //1.Array对象
        var arr = [10,20,30];// new Array(10,20,30)

        //查看数组对象的原型链
        console.log(arr.__proto__.constructor);//Array
        console.log(arr.__proto__ === Array.prototype);//true

        //查看数组对象的原型的原型
        console.log(arr.__proto__.__proto__.constructor);//Object
        console.log(arr.__proto__.__proto__ === Object.prototype);//true

        console.log(arr.__proto__.__proto__.__proto__);//null

        console.log(arr);

        arr.push();//js作者将数组所有的API都放入了Array。prototype中,这样所有的数组对象都可以直接调用

        arr.toString();//所有的对象原型链都会指向Object.prototype,这就意味着任何对象都可以调用Object原型中的方法
        
        
        //2.Date对象

        var date = new Date();
            细节:日期对象不能直接用log,会自动转成toString字符串
        console.log(date);
        //查看对象内存空间  console.dir()
        console.dir(date);

        //查看date的原型
        console.log(date.__proto__.constructor);//Date
        console.log(date.__proto__ === Date.prototype);//true

        //查看date的原型的原型链
        console.log(date.__proto__.__proto__.constructor);//Object
        console.log(date.__proto__.__proto__ === Object.prototype);//true
        
        
        //3.String对象(基本包装类型  new String new Number new Boolean)
        var str = new String('123');
        console.log(str);

        //查看str对象的原型
        console.log(str.__proto__.constructor);//String
        console.log(str.__proto__ === String.prototype);//true

        //查看str对象原型的原型
        console.log(str.__proto__.__proto__.constructor);//Object
        console.log(str.__proto__.__proto__ === Object.prototype);//true
        
        
        //4.DOM对象

        var box = document.getElementById('box');
        var p1 = document.getElementById('p1');

        console.log(box);//打印HinnerHTML
        console.dir(box);//打印对象内存空间
        console.dir(p1);

3.函数也是对象类型: 验证:对象拥有点语法动态添加属性,如果函数也能像对象一样拥有点语法动态添加属性

  function fn(){
            console.log('11111');
        };

        fn.sb = function(){
            console.log('一群大雁飞过,一会儿拍成了s形,一会儿又拍成了b形');
        };

        fn.aaa = '我是函数的属性';


        fn.sb();
        console.log(fn.aaa);

        //log:打印函数中存储的代码
        console.log(fn);
        //dir:打印函数对象中存储的属性
        console.dir(fn);

        //2.既然函数也是对象(所有的对象都是构造函数创建),那么函数对象又是谁创建的呢?

        /* 函数是一个特殊的对象,所有的函数都是由Function构造函数创建 */
        console.log(fn.__proto__.constructor);//Function
        console.log(fn.__proto__ === Function.prototype);//true


        console.log(Object.__proto__.constructor);//Function
        console.log(Array.__proto__.constructor);//Function

由上面的介绍基本上已经可以大概了解原型链的雏形啦,下面就是原型链的完整版

06-完整的原型链.png

由原型对象看instanceof

 <script>
        /* 
        instanceof运算符工作原理:   对象 instanceof 构造函数
            规则: 检查右边构造函数的原型,在不在左边对象的原型链中
         */

        //1.Array
        /*根据instanceof的运算规则: 左边Array是对象,右边是构造函数
        Array构造函数对象的原型链:Array对象.__proto__ -> Function.prototype -> Object.prototype -> null 
        
         */
        console.log(Array instanceof Object);//true
        console.log(Array instanceof Function);//true
        console.log(Array instanceof Array);//false

        //2.Function
        /* 
        根据instanceof运算符规则:左边Function是对象,右边的Function是构造函数

        Function对象的完整原型链: Function -> Function.prototype - > Object.prototype -> nulll

         */

        console.log(Function instanceof Function);//true
        console.log(Function instanceof Object);//true


        //3.Object
        /* 
        根据instanceof运算符规则:左边Object是对象,右边的Object是构造函数

        Object对象的完整原型链: Object -> Function.prototype - > Object.prototype -> nulll

         */
        console.log(Object instanceof Function);//true
        console.log(Object instanceof Object);//true 
    </script>