JS prototype属性详解

不少人对于原型和原型链一知半解或者不熟悉,看了网上的文章之后依旧一脸懵逼,曾今的我就是如此,多次从接触到放弃,几经周折终于弄明白了。我写这篇文章,是希望你能减少走的弯路,避免一些坑。

	var Fun = function(){};

在定义完Fun之后,你可以发现Fun可以调用的方法属性有很多(length,constructor,caller等等),但是为什么会这样?明明我就定义了一个函数,我都没给它添加属性方法怎么就有了?有人说TA是一个函数对象自然有函数的方法和属性。但是我想问为什么?有人问过为什么吗?这些方法属性从何而来又是从哪里定义的呢?我们回归函数被定义时寻找答案,每一个对象(函数也可以看做对象,毕竟万物皆对象嘛)被定义时都会带有一个__proto__属性,这个属性指向一个对象,当你调用Fun某个属性时而Fun本身没有时,TA就会去__proto__属性所指向的对象里寻找,当__proto__所指向的对象里也没有时,TA(__proto__)就会去自己的__proto__找,这样一直一直往上找,形成也链状(即原型链),最终到了object.__proto__也就是null,还是找不到的话,就说明Fun没有这个属性。

所以你该知道为什么我就声明了一个函数,什么也没写Fun就有怎么多属性方法了吧,因为TA通过__proto__往上寻找把能找到的都归为自己的所以就有什么多了。那我们怎么知道这个__proto__指向哪个对象啊?如果是随意指向的话,那我不就有了全世界的方法和属性吗?的确如此,我们自身定义的对象的__proto__是可以被修改的,你把__proto__指向一个对象你就获得了这个对像的方法和属性(包括TA从__proto__找到的),这也就是我们所说的继承了。我们试着断掉Fun的集继承看看结果会怎么样


	var Fun = function(){};			
        Fun.__proto__ = null


我们会发现Fun的属性和方法仅剩寥寥几个了,但是仅剩的属性方法又是怎么来的?默认__proto__指向怎么确认?别着急,我们慢慢细说


    var Fun = function(){this.parent = "Fun";};
	var fun = new Fun();



上面代码我们做了什么,我们是不是实例化了一个对象fun,我们看一下fun的属性方法,很多,大都是继承的我们知道,然后我们断掉继承操作跟上面一样 fun.__proto__ = null ,发现fun仅剩下一个属性了parent了,我们都知道parent是怎么来的,TA是在Fun里定义的,所以现在你知道Fun断掉继承后,仅剩的属性怎么来了吧.没错是在Function里面定义的,只是我们看不到而已。说了这么多我好像还没提到prototype,别着急,我们现在再来分析就比较简单了。我们都知道fun继承了Fun,但是fun的__proto__继承哪个对象?Fun吗?并不是,fun的__proto__指向是Fun的prototype所指向的对象,为什么不直接指向Fun?这个我们之后再作探讨。每一个函数都有prototype(只有函数有,因为从Function那里来的),函数的prototype属性是一个对象,里面的方法属性用于继承,当然在函数内部定义自身属性方法也可以被继承.那这两者有什么差别呢?再看一段代码


    var Fun = function(name,age){this.name = name;this.age = age;};
	Fun.prototype.parent = "Fun";
	var fun1 = new Fun('fun1',18);
	var fun2 = new Fun('fun2',18);


上面代码我们做了什么,我们是不是实例化了一个对象fun,我们看一下fun的属性方法,很多,大都是继承的我们知道,然后我们断掉继承操作跟上面一样 fun.__proto__ = null ,发现fun仅剩下一个属性了parent了,我们都知道parent是怎么来的,TA是在Fun里定义的,所以现在你知道Fun断掉继承后,仅剩的属性怎么来了吧.没错是在Function里面定义的,只是我们看不到而已。说了这么多我好像还没提到prototype,别着急,我们现在再来分析就比较简单了。我们都知道fun继承了Fun,但是fun的__proto__继承哪个对象?Fun吗?并不是,fun的__proto__指向是Fun的prototype所指向的对象,为什么不直接指向Fun?这个我们之后再作探讨。每一个函数都有prototype(只有函数有,因为从Function那里来的),函数的prototype属性是一个对象,里面的方法属性用于继承,当然在函数内部定义自身属性方法也可以被继承.那这两者有什么差别呢?再看一段代码
我们来看看fun1和fun2的差异,fun1和fun2都有继承的三种属性name,age,parent,其中name和age是根据实例化时传入参数的数值改变而改变,并且已经脱离与父对象的关联,就是说父对象怎么对name和age做修改都跟TA们两没关系了,因为已经实例化变成自己的属性,那假如我想修改某个对象的属性并且他所实例化的对象的属性也会改变,那么我们就必须用到prototype。当我们修改Fun的prototype指向的对象的值,fun1和fun2的相对应属性也会被修改,为什么?因为TA们这个属性是通过找别人属性得到的,并不是自己的(相当于映射),别人修改了TA还不是要修改。其实我们可以认为fun跟Fun是完全没有联系的,为什么?因为在实例化之后name和age都是自身属性不关Fun什么事了,其次fun的__proto__继承是Fun.prototype所指向的对象,这个对象跟Fun没有半毛钱关系,只是你能通过Fun的prototype找到这个对象和修改这个对象而已,再举个例子


    var Fun = function(){};
	Fun.prototype.parent = "Fun";
	var fun2 = new Fun();
	Fun.prototype= null;
	console.log(fun2.parent)


上面代码我们做了什么,我们是不是实例化了一个对象fun,我们看一下fun的属性方法,很多,大都是继承的我们知道,然后我们断掉继承操作跟上面一样 fun.__proto__ = null ,发现fun仅剩下一个属性了parent了,我们都知道parent是怎么来的,TA是在Fun里定义的,所以现在你知道Fun断掉继承后,仅剩的属性怎么来了吧.没错是在Function里面定义的,只是我们看不到而已。说了这么多我好像还没提到prototype,别着急,我们现在再来分析就比较简单了。我们都知道fun继承了Fun,但是fun的__proto__继承哪个对象?Fun吗?并不是,fun的__proto__指向是Fun的prototype所指向的对象,为什么不直接指向Fun?这个我们之后再作探讨。每一个函数都有prototype(只有函数有,因为从Function那里来的),函数的prototype属性是一个对象,里面的方法属性用于继承,当然在函数内部定义自身属性方法也可以被继承.那这两者有什么差别呢?再看一段代码
毫无疑问,Fun.prototype 在被赋空值后,fun还是拥有parent属性,假如fun继承的是Fun.prototype的话那么fun的parent属性应该是没了但是现在还在,就说明fun跟Fun.prototype属性没关系,跟TA最初所指的对象有关,那怎么再次找到这个对象?fun.__proto__就指向这个对象嘛,既然fun.__proto__指向这个对象,那自然也可以修改里面的值了那还要Fun干什么?所以fun1和fun2可以修改该对象的值,达到修改全部的效果。看看下图,可能会更加直观。




关于prototype和__proto__或许你已经开始有了初步认识了,我们开始通过他们了解更多。嗯,我好像忘了讲constructor了,没关系,这个很简单,这个属性存在于每一个函数的prototype对象中,值指向函数本身,说完。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值