本篇仅仅介绍js中常说到的继承、闭包、原型链以及其具体实例,然后会提及其项目中的具体应用场景。还是那句话,请提出您的宝贵建议!
作为前端大军中的一员,曾一度认为JavaScript不是面向对象语言,学习了一些如python、c#等语言后,其实这种问题就不该纠结或者去思考,从语言的作用出发,我们为了更好的使用其特色与大环境(类、对象、接口等名词)的结合,JavaScript中很多也用到了强类型语言很多的模式和思想,如果真得要给它一个定义:“弱类型的面相对象语言”
JavaScript中对象的理解:数组是对象,函数是对象,对象还是对象。对象里面的一切都是属性,只有属性,没有方法。那么这样方法如何表示呢?——方法也是一种属性。因为它的属性表示为键值对的形式。
所以有结论: JavaScript中,一切引用类型都是对象,对象是属性的集合。
论证以上观点4,日常可别这样写!其他的结论有:
1, 对象都是由函数创建 (函数又是对象的一种,很有趣吧,可理解为函数对象和普通对象的区别)
2,每个对象都有一个_proto_隐形属性,指向创建该对象的函数的prototype
3,Object.prototype的_proto_指向的是null, 最终都会指向null
4,函数由Function创建得到,故Object.__proto__ === Function.prototype
5,Function.prototype.constructor===Function
【原型链示意图,不做过多解释】解释1,2,3,5,注:图片来源http://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/figure1.jpg
一,JavaScript中的继承 (instanceof体现)
继承的方式很多,大家也很清楚为什么要实现继承(为了偷懒啦!装逼啦!),在真实的IO特多的项目中,我们几乎可能不会用到它,但是如果,我说的是如果,比如需要在客户端维持数据增量呀,主动更新呀,处理个体差异呀的时候,再加上如果你在改别人写的代码的时候,就会明白为什么前人不用继承不用对象的思维去处理某个节点某段逻辑过程。
证明:f1._proto_是指向fn.prototype(原型), 即实例的_proto_指向父函数的prototype
其实,说到这里,大家已经很明白,当我们输出f1.hasOwnProperty属性时,它也会存在,问题是我们没有对其进行声明定义,这是默认的Object.prototype上早已定义的。
来吧,直接说那些个xx模式吧,虽然我也不喜欢记这些名词,就好像记算法的名字一样。。
1,工厂模式, 这里有2个地方,实例化的时候别new,属性最好定义在外部函数(可能变动大的)
2,构造函数方式 3,原型模式
4,混合的构造函数-原型方式(这里有一个问题,当我们new一个实例的时候,如果属性已经存在,那么就会重复创建)
所以,这里是4的改进版啦!
二,闭包
使用闭包,会增加内容开销,体现在闭包会维持一些变量的状态,比如,函数执行时,返回的是一个函数,而这个函数会创建一个独立的作用域,外部函数调用完后,理应被销毁,包括其执行上下文和函数作用域中的变量,如果返回的函数中恰恰也用到了外部函数声明的变量,那么这个外部函数的执行上下文就不能被销毁。
闭包体现在:函数作为返回值和函数作为参数。
返回函数可以访问该函数外部的name,这个name即实现了私有成员
闭包的作用:
1,将函数内部和函数外部连接起来(js函数作用域的问题,函数内部可访问函数外部的变量,而外部无法访问到内部的变量)
2,让变量的值始终保持在内存中(缺点在上述已经说明)
闭包的优缺点:
1,变量常驻内存(不用重复声明初始化,某些场景下是很有利的,与此同时增加了内从的使用量,而且使用不当容易造成内存泄漏)
2,避免全局变量的污染,也实现了类似于其他语言的私有变量的的存在
结论:1,不使用prototype属性定义的对象方法(也是属性啦),是静态方法,只能通过对象名+属性名进行调用,且不能使用this来调用对象的属性;2,使用prototype定义的对象方法,需要实例化才能使用,可以使用this来引用对象自身的其他属性。推论:变量的作用域在变量声明的时候就决定的,外部无法访问,要访问的方法只能是new一个实例出来,重新实现该变量声明的过程。
最后切记一点:new Object() 是一个对象,它没有prototype属性,所以不能new,但对象有_proto_隐形属性,指向创建该对象的函数的prototype, 而Function是函数,有prototype属性,可以实现new。
网友评论