JS的原型链

原型链:利用原型让一个引用类型继承另外一个引用类型的属性和方法
原型链是继承的主要方法
简单讲一下构造函数,原型和实例的关系
> 每一个函数都有一个原型对象,原型对象都包含一个指向自己的构造器指针,而实例都包含一个指向原型对象内部的指针。假如,我们让原型对象等于另一个类型的实例,结果会怎么样呢?显然,此时的原型对象将包含一个指向另一个原型对象的指针,相应的,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。

这里写图片描述

<script>
    // js中的数据类型(值类型和引用类型)
    //基本数据类型,SBNUN(特殊的值类型:NULL)
    console.log(typeof x);  //undefined
    console.log(typeof 10); //number
    console.log(typeof 'abc');  //string
    console.log(typeof true);   //boolean
    console.log(typeof null);   //object
    console.log('------我是分割线------');

    //引用数据类型:object,array,function
    console.log(typeof function(){});   //function
    console.log(typeof [1,2,3]);    //object
    console.log(typeof {a:5,b:3});  //object
    console.log(typeof new Number(10)); //object
    console.log('------我是分割线------');
    //原型链(继承的主要方法):利用原型让一个引用数据类型继承另一个引用类型的方法和属性
    //一切引用数据类型都叫做对象,对象是一堆属性的集合(对象,数组,函数)
    //函数和对象的关系
    function fn1() {
        this.name="安子晗";
        this.age=18;
    }
    var objFn1 = new fn1();
    console.log(objFn1);    //fn1 {name: "安子晗", age: 18}
    console.log(typeof fn1);    //function
    // 上述说明个啥问题:对象是由函数创建的
    console.log('------我是分割线------');

    var obj = {a: 1, b: 2};
    var arr = [1,2,3];
    // 这其实是编程语言中一个叫语法糖的东西
    // 啥叫语法糖,就是为了让程序员编写代码更为方便的一个东西,把猫叫个咪。比如C里面的,a[i]和*(a+i)是一样的,对代码并没有什么改变
    // 那上述代码其实就等价:

    //Object(),Array()
    var obj1 = new Object();
    obj1.a = 1;
    obj1.b = 2;
    var arr1 = new Array();
    arr1[0]=1;
    arr1[1]=2;
    arr1[2]=3;
    console.log(obj);   //{a: 1, b: 2}
    console.log(obj1);  //{a: 1, b: 2}
    console.log(arr);   //(3) [1, 2, 3]
    console.log(arr1);  //(3) [1, 2, 3]
    console.log(obj + '---obj, ', obj1 + '---obj1');    //[object Object]---obj,  [object Object]---obj1
    console.log(arr + '---arr, ', arr1 + '---arr1');    //1,2,3---arr,  1,2,3---arr1
    console.log(typeof Object);     //function
    console.log(typeof Array);      //function
    console.log('------我是分割线------');

    // function和object的关系
    //既然函数是对象,那它就是属性的集合,可以随意去扩展自己的自定义属性
    //所以函数默认有prototype属性,也就是原型
    //原型也是一个对象,所以他有一个默认属性constructor,指向了函数本身
    function superClass(name,sex,age) {
        this.name= name;
        this.sex= sex;
        this.age=age;
    }
    console.log(superClass.prototype.constructor ===superClass);    //true
    console.log(Object());  //打印出来是Object的所有默认属性
    // 既然可以随意扩展,那我们就可以给自己的构造函数里面扩展属性:
    superClass.prototype.print = function () {
        console.log("罗怡是美女");
    };
    var superClassObj = new superClass("罗怡",18,"女");
    superClassObj.print();      //调用结果是打印出来"罗怡是美女"
    //所以,new出来的这个superClassObj实例也是个对象,并且继承了superClass的方法
    //实例对象里面,__proto__隐式属性,叫隐式原型,指向了创建这个对象的函数的prototype
    console.log(superClassObj.__proto__===superClass.prototype);     //true
    var obj2 = {};
    console.log(obj2.__proto__===Object.prototype);     //true
    // 既然Object.prototype和superClass.prototype也是对象,那他们的_proto_属性指向谁?
    // 先说superClass.prototype,它其实就和var obj = {}是一样的,都是由Object创建,
    // 所以自定义函数的prototype的_proto_指向了Object的prototype。
    console.log(superClass.prototype.__proto__===Object.prototype);      //true
    // 但Object.prototype的__proto__却是个特例,他指向了null,null生万物
    console.log(Object.prototype.__proto__);    //null
    console.log('------我是分割线------');

    // 那函数也是对象啊,函数也是有_proto_的,所以下面讨论函数的__proto__指向
    function createFun(x,y){
        return x+y;
    }
    console.log(createFun(2,3));     //5
    var otherCreateFun = new Function("x","y",'return x+y');
    console.log(otherCreateFun(2,3));   //5
    // 证明函数这个对象是由Function这个构造函数创建的
    console.log(createFun.__proto__===Function.prototype);  //true
    //构造函数Function也是一个对象,那它的__proto__指向谁?
    console.log(Function.__proto__===Function.prototype) ;   //true
    //Function的prototype也是对象,那它的prototype指向谁?
    console.log(Function.prototype.__proto__===Object.prototype);   //true
    //构造函数Object也是一个函数,那同时作为对象的它的__proto__指向谁
    console.log(Object.__proto__===Function.prototype);     //true
    console.log(superClass.__proto__===Function.prototype); //true
    console.log('------我是分割线------');

    //typeof只能判断值类型,只能返回Object或者Function
    //所以如果要判断一个引用类型的值是对象还是数组,要用到instanceof来判断引用类型
    //instanceof的判断规则:
    //A instanceof B ,A沿着__proto__这条线找,B沿着prototype这条线找
    //如果能找到同一个引用,证明是同一个对象,则返回true,若找不到,则返回false
    var arr2 = [1,2,3];
    console.log(typeof arr2);               //Object
    console.log(arr2 instanceof Array);     //true
    console.log(superClassObj instanceof Object);   //true
    console.log(arr2 instanceof Function);  //false
    console.log(arr2 instanceof Object);    //true
    //arr2.__proto__===Array.prototype; Array.prototype.__proto__===Object.prototype
    console.log(Array.prototype.__proto__===Object.prototype);  //true
    console.log('------我是分割线------');

    // objSuperClass是构造函数superClass new出来的实例
    // 那么我们也就可以实现面向对象最基本的——继承ass的原型上定义一些自定义属性,
    // 那么new出来的实例也能继承这些属性了
    superClass.prototype.add = function () {
      var sum = 0;
      for(var i=0;i < arguments.length; i++){
          sum += arguments[i];
      }
      return sum;
    };
    var superClassObj1 = new superClass();
    console.log(superClassObj1.add(2,3,5));     //10
    // 当访问一个对象的属性的时候,会先在自身的基本属性中查找,当自身没有的时候,再沿着_proto_这条链向上找,这就是原型链
    // 那如何判断一个属性是存在自身还是存在与原型中呢?要用到hasOwnProperty
    // 那hasOwnProperty从哪来的,它是继承与Object.prototype,objSuperClass1并没有这个方法.这就是原型链继承
    console.log(superClassObj1);
    var item;
    for (item in superClassObj1) {
        console.log(superClassObj1.hasOwnProperty(item));
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值