最近在看《编写高质量代码-web前端修炼之道》,写了3篇博客,写写感想。javascript
第一篇写了关于javascript封装以及模块化插件设计。php
第二篇写了关于javascript面向对象思想以及原型和构造器。前端
第三篇主要写关于javascript的编写风格以及细节设计问题。java
继上一篇javascript进阶,关于js插件开发的mvc思想,此次继续写篇博客,主要说说关于javascript的面向对象思想。python
1、关于javascript类的定义android
首先,javascript是面向对象语言,可是js没有class类,而是经过:web
new funName( );
来声明。segmentfault
javascript使用基于原型的语言,经过new实例化对象,其属性和行为来自两部分,原型和构造函数。数组
当咱们声明一个类时,同时生成了一个对应的原型。例如咱们声明了:A这个类,会同时生成与这个类对应的原型。A.prototype指向原型,原型能够经过coustructor指向构造函数。写个代码你就懂。数据结构
function A(){ } var x = A.prototype; var y = x.constructor; alert(y==A); //return true; console.log("也就是说A.prototype.constructor=A");
当咱们声明类时候,新的构造函数会把旧的prototype原型给覆盖掉。
给你看个例子。
function A(){ this.a="属性a"; this.b="属性b"; this.fun1=function(){ alert("这是函数对象1"); }; this.fun2=function(){ alert("这是函数对象2"); }; } var B = new A(); B.fun1=function(){ alert("你是笨蛋!!"); }; B.fun1(); //结果为alert("你是笨蛋!!"); console.log("也就是说构造函数声明的属性会覆盖原型的函数"); ```
从上面的例子里咱们能够看到,原型中的函数是会随声明的属性或者方法是会被实例化过程声明覆盖。
通常来讲,咱们习惯在构造函数里放属性,在原型里面放方法。给你个例子看看:
/*===========构造函数放属性,原型里放方法============*/ function A(){ this.a="属性a"; this.b="属性b"; } A.prototype={ fun1:function(){ console.log("这是函数对象1,咱们把它放在原型里"); }, fun2:function(){ console.log("这是函数对象2,咱们一样也把它放在原型里"); } }; var B = new A(); B.fun1(); B.fun2(); console.error("这样就整洁多了。");
<br> **2、公有和私有** js里面没有相似php同样的权限设置,但是若是我想要一个变量是私有属性怎么办?须要注意的一点是,只要写在原型里的无论是属性仍是方法,都是公有性的。因此要怎样才能让一个变量私有化呢?看看例子: ```js /*===============原型中的共有域和私有域================*/ function A(){ var a="属性a是私有的,在类外面你是调用不到的。"; this.b="属性b是公有的"; var fun1=function(){ console.log("函数对象1是私有的,在类外面你是调用不到的。"); }; this.fun2=function(){ console.log("函数对象2是共有的"); }; } A.prototype={ fun3:function(){ console.log("这是函数对象3,在原型里的,只能是公有的"); } }; var B = new A(); B.a; //not found a; B.b; //返回正常 B.fun1(); //not found B.fun2(); B.fun3();
须要强调的一点是,原型中的属性和方法,只存在一份,是公用的,在实例化的时候,并不会在复制一遍。因此,作到了代码的重复利用,可是,若是把属性和方法都放在构造函数里,也同时致使了代码修改的麻烦。
问题出来了,你想下,那咱们若是有一个属性,不少函数都要调用他,想把它放在原型里,可是又不想把让它公有友化,怎么破?怎么破?
答案是:无法破。
因而,命名规则出来了,咱们规定,在命名前对一个下划线,表示私有属性。例如:
A.prototype={ _value:"咱们规定,这个属性为私有属性(ps:其实它就是公有的)"; };
因而有些比较倔强的码农们就提出来了一套新方案。请看:
/*=============私有与公有域==============*/ function A(){ this.a="属性a是公有的。"; this.b="属性b是公有的"; this.set_a=function(value){ this.a=value; }; this.get_a=function(){ return this.a; }; this.call=function(name){ console.log(this.get_a(name)); }; } var B = new A(); B.set_a("我把值改了"); B.call("a"); //return 我把值改了
看了好别扭,可是这样你就能够在属性或者方法的值改变时候,直接留下回调函数。
3、继承
我在上一篇博客封装过关于继承的函数。由于在javascript里面没有继承,可是继承的思想又是存在于面向对象语言里。
若是没有函数,咱们要怎么继承?最笨的是,类A和类B,我把A的全部属性和方法抄一遍。好傻啊,不适合。
/*==================关于声明中的this==================*/ function A(){ this.a="属性a是公有的"; this.b="属性b是公有的"; } A.prototype={ say:function(){ console.log(this.a); } }; function B(value){ this.a=value; A(); } var C = new B(); //你觉得这么就能继承了么??天真了,试试看 C.say(); //return undefind
哈哈,知道了吧,想知道为何吗?
js函数调用有两种方法,
第一种是直接调用,此时,它做为函数;
第二种是经过实例化,构造函数调用;
没问题啊,可是,它们返回的this对象就不一样了,第一种,做为函数调用,返回的是window对象,可是第二种调用返回的是实例对象自己。因此说不能直接调用继承。
咱们把this指向改下吧:
function A(){ this.a="属性a是公有的"; this.b="属性b是公有的"; } A.prototype={ say:function(){ console.log(this.a); } }; function B(value){ A.call(this,value); A(); } var C = new B(); //能够了 C.say(); //找到值了
/*================相同原型继承==================*/ function A(){ this.a="属性a是公有的"; this.b="属性b是公有的"; } A.prototype={ say:function(){ console.log(this.a); } }; var B =function(){ }; B.prototype = A.prototype; B.prototype.test=function(){ console.log("继承后添加的函数"); }; var C = new B(); C.test(); //return console.log("继承后添加的函数"); var D = new A(); D.test(); //return console.log("继承后添加的函数");
为何??为何我只是在B中添加了test方法,可是我在A中也感染了??
由于javascript在赋值时候,若是判断出值是布尔,字符串,数值型等基本数据类型,会直接复制值,可是,赋值,数组,方法,对象等复杂数据,一般都会地址复制,因此,把A的原型也改了。
咱们再试试,改回来,哪错改哪。
function A(){ this.a="属性a是公有的"; this.b="属性b是公有的"; } A.prototype={ say:function(){ console.log(this.a); } }; var B =function(){ }; B.prototype = A.prototype; C.prototype.constructor=A; B.prototype.test=function(){ console.log("继承后添加的函数"); }; var C = new B(); C.test(); //return console.log("继承后添加的函数"); var D = new A(); D.test(); //return not defind
这样就行了。
最后给下,extend的具体函数把,这样就不要一个一个地来弄了,你只要调用函数就行了。
function extend(subClass, superClass){ var C=function(){}; C.prototype=superClass.prototype; subClass.prototype=new C(); subClass.prototype.constructor=subClass; subClass.superClass=superClass.prototype; if(superClass.prototype.constructor == Object.prototype.constructor){ superClass.prototype.constructor=superClass; } } /*=====搞定了=====*/
写下最近的在作什么吧:
看了《javascript高质量代码》;
给新生培训了下,写了篇博客;
看了一点点的php数据结构
写写接下来作什么吧:
《python基础教程》(华哥的项目,日志分析系统)
《精通android 4》(东哥)
期末了,要开始复习了。
(睡觉去。。。)
夏日小草
2013/12/3 1:57:07
(ps:若是有出错,求指点出来。)