JS原型,原型链

   楼主作为一名前端小白,虽然已经学习前端有了将近一年的时间,但是总是觉得前端有太多值得我们去深究的内容了;在学习的过程中也看过很多的别人的博客和很多别人自己搭的博客,现在我也有了自己的博客,我也希望可以在我自己的论坛去展示我自己的微薄的见解!
  在我的认知中,前端还属于一个很新兴的行业,在以往的软件行业基本上后端可以把所有的事情都解决了,但是通过后端来解决问题就无法解决前后端分离的问题,学后端的开发人员不光需要了解后端知识,还要了解前端的基础内容,这样就给开发人员造成了很大的困扰;现在有了前端工程师的概念,之前都要后端人员做的工作转移到前端开发人员的手上,不但加快了项目的进度,也减轻了对程序员的苛刻;今天从网上看了一些关于JavaScript核心内容的部分(汤姆大叔的博客,推荐大家去度年一下),想分享一些自己对JavaScript核心的理解,原型,原型链
    原型:(1)在JS中,所有的对象(也有人说函数)都有一个prototype属性,被称作原型对象;原型的值也是一个对象,因此他也会有属于自己的原型对象,这一串联起来就构成了原型链,原型链的头是object,只不过他比较特殊,他的prototype为null;JS中的对象分为两种,一种是object对象,一种是函数对象function
 function fn1(){};
    var fn2 = function(){};
    var fn3 = new Function();
    var fn4 = Function();

    var obj1 = new fn1();
    var obj2 = {};
    var obj3 = new Object();
    var obj4 = Object();

    console.log(typeof fn1);//function
    console.log(typeof fn2);//function
    console.log(typeof fn3);//function
    console.log(typeof fn4);//function

    console.log(typeof obj1);//object
    console.log(typeof obj2);//object
    console.log(typeof obj3);//object
    console.log(typeof obj4);//object

普通对象是没有prototype属性的,只有隐藏的属性proto(IE上也有该隐藏属性,只不过是obj.proto不能输出东西,所以建议不要使用proto属性),prototype属性指向的是函数对象的原型对象,对象的proto属性是创建实例对象的时候对应的函数对象的原型对象;
在JS中实例化一个对象的步骤如下:

function A(x){
  this.x=x;
}
var obj=new A(1);
    1,创建一个新对象,这个对象的的类型为object,并让this(这个this是指全局对象还是实例化该对象的当前函数,LZ不太懂)指向他;
    2,将obj对象的内部_proto_属性指向构造他的函数A的prototype,同时,obj.constructor=A.prorotype.constructor(这个永远成立,即:类的实例对象的constructor属性永远指向“构造函数”的prorotype.constructor);从而是obj.constructor.prototype指向A.prorotype(obj.constructor.prototype===A.prototype,当A.prototype改变时则不成立)。obj.constructor.prototype 与内部的_proto_是两个东西,实例化对象的时候使用的是_proto_,obj是没有prototype属性的,但是有内部的_proto_,通过_proto_来取得原型链上的原型属性和原型方法;
    3,将obj作为this去调用构造函数A,设置成员函数并初始化;

(2)原型与继承


function A(x){
2   this.x = x;
3 }
4 A.prototype.a = "a";
5 function B(x,y){
6   this.y = y;
7   A.call(this,x);
8 }
9 B.prototype.b1 = function(){
10   alert("b1");
11 }
12 B.prototype = new A();
13 B.prototype.b2 = function(){
14   alert("b2");
15 }
16 B.prototype.constructor = B;
17 var obj = new B(1,3);
这个例子讲的就是B继承A。第7行类继承:A.call(this.x);上面已讲过。实现原型继承的是第12行:B.prototype = new A();

  就是说把B的原型指向了A的1个实例对象,这个实例对象具有x属性,为undefined,还具有a属性,值为”a”。所以B原型也具有了这2个属性(或者说,B和A建立了原型链,B是A的下级)。而因为方才的类继承,B的实例对象也具有了x属性,也就是说obj对象有2个同名的x属性,此时原型属性x要让位于实例对象属性x,所以obj.x是1,而非undefined。第13行又定义了原型方法b2,所以B原型也具有了b2。虽然第9~11行设置了原型方法b1,但是你会发现第12行执行后,B原型不再具有b1方法,也就是obj.b1是undefined。因为第12行使得B原型指向改变,原来具有b1的原型对象被抛弃,自然就没有b1了。

  第12行执行完后,B原型(B.prototype)指向了A的实例对象,而A的实例对象的构造器是构造函数A,所以B.prototype.constructor就是构造对象A了(换句话说,A构造了B的原型)。

alert(B.prototype.constructor)出来后就是”function A(x){…}” 。同样地,obj.constructor也是A构造对象,alert(obj.constructor)出来后就是”function A(x){…}” ,也就是说B.prototype.constructor===obj.constructor(true),但是B.prototype===obj.constructor.prototype(false),因为前者是B的原型,具有成员:x,a,b2,后者是A的原型,具有成员:a。如何修正这个问题呢,就在第16行,将B原型的构造器重新指向了B构造函数,那么B.prototype===obj.constructor.prototype(true),都具有成员:x,a,b2。

  如果没有第16行,那是不是obj = new B(1,3)会去调用A构造函数实例化呢?答案是否定的,你会发现obj.y=3,所以仍然是调用的B构造函数实例化的。虽然obj.constructor===A(true),但是对于new B()的行为来说,执行了上面所说的通过构造函数创建实例对象的3个步骤,第一步,创建空对象;第二步,obj.proto === B.prototype,B.prototype是具有x,a,b2成员的,obj.constructor指向了B.prototype.constructor,即构造函数A;第三步,调用的构造函数B去设置和初始化成员,具有了属性x,y。虽然不加16行不影响obj的属性,但如上一段说,却影响obj.constructor和obj.constructor.prototype。所以在使用了原型继承后,要进行修正的操作。

  关于第12、16行,总言之,第12行使得B原型继承了A的原型对象的所有成员,但是也使得B的实例对象的构造器的原型指向了A原型,所以要通过第16行修正这个缺陷。
  原型链:在使用new来初始化对象的时候,得到的新对象的的proto属性会指向函数对象的原型对象;而函数对象的原型对象有继承自原始对象
  把这个由proto串起来的直到Object.prototype.proto为null的链叫做原型链,原型链实际上就是JS中数据继承的继承链,主要完成JS中的继承问题!
  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值