var add=function(a,b){if(typeof a!=='number'){throw{'name':'TypeError','message':'add needs numbers'};}return a+b;}
第五章 继承
继承是大多数编程语言非常重要的主题。良好的继承不仅可以使你的系统有逻辑性和层次感,更重要的是可以减少你的代码量和开发成本。
5.1伪类
在本节中作者试图隐藏prototype对象,而尽量使用一种类似“类”的方式实现继承,他的做法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | Function.prototype.method= function (name,func){ if (! this .prototype[name]){ this .prototype[name]=func; } return this ; } //通过method方法定义一个inherits方法,目的是隐藏prototype实现继承 Function.method( 'inherits' , function (Parent){ this .prototype= new Parent(); return this ; }); /*以上是准备工作*/ var Mammal= function (name){ this .name=name; } Mammal.prototype.get_name= function (){ return this .name } Mammal.prototype.says= function (){ return this .saying|| '' ; } //继承来了,采用的是级联的样式编程,只有一条语句 var cat= function (name){ this .name=name; this .saying= 'meow' ; }.inherits(Mammal). //继承Mammal method( 'get_name' , function (){ //在cat的原型上添加方法 return this .says()+ ' ' + this .name+ ' ' + this .says(); }); |
这种伪类的方式作者提出了几个缺点:
1.没有私有环境,所有属性都是公开的。
2.无法访问super(父类)的方法。 (这点不太理解,构造一个子类的对象不就可以访问了吗?)
3.如果你在调用构造器时忘记使用new了,危害相当大!所以建议构造器函数用大写字母。
5.2对象说明符
就是说构造器在参数设定上,尽量用一个对象,这样能更好的表达出语义。如:
1 2 3 4 5 6 | var myobject=maker(f,l,m); //不好的方式 var myobject=maker({ //比较好的方式 first:f, last:l, male:m }); |
5.3原型
5.1讲的是javascript用“类”的方式实现继承,这一节介绍怎么用原型的方式继承。直接上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //为Object对象增加一个方法,这个方法的作用实际上是实现了一次对对象的拷贝 if ( typeof Object.beget!== 'function' ){ Object.beget= function (o){ var F= function (){}; F.prototype=o; return new F(); }; } var myMammal={ name: 'xxx' , get_name: function (){ this .name; }, says: function (){ return this .saying|| '' ; } } var myCat=Object.beget(myMammal); //重点来了,这句是实现了对myMammal对象的继承 myCat.name= 'mimi' ; myCat.get_name= function (){ return this .says()+ " " + this .name; } |
5.4函数化
这里其实又介绍了一个设计模式--函数化模式,个人感觉跟模块模式差不多,都是在内部定义私有变量、私有方法,然后通过特权方法对外提供访问接口。看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | var mammal= function (spec){ var that={}; that.get_name= function (){ return spec.name; } that.says= function (){ return spec.saying|| '' ; } } var mymammal=mammal({name: 'Herb' }); var cat= function (spec){ spec.saying=spec.saying|| 'meow' ; var that=mammal(spec); //继承父类 that.get_name= function (){ return that.says+ ' ' +spec.name; } return that; } var mycat=cat({name: 'Joge' }); |
若要访问父类的方法,本书作者提供了一种装逼的写法(个人感觉没什么必要)
1 2 3 4 5 6 | Object.method( 'superior' , function (name){ var that= this ,method=that[name]; return function (){ return method.apply(that,arguments); }; }); |
1 2 3 4 5 6 7 8 9 10 | var coolcat= function (spec){ var that=cat(spec), super_get_name=that.superior( 'get_name' ); //调用父类方法get_name that.get_name= function (n){ return 'like ' +super_get_name()+ ' baby' ; } return that; } var mycoolcat=coolcat({name: 'Bix' }); var name=mycoolcat.get_name(); //'like meow Bix meow baby' |
第六章 数组
数组其实没什么好说的,他在javascript中就是一个对象。不同的是数组继承自Array.prototype,而不是Object.prototype。而且数组拥有length属性和很多实用的方法。
(1)删除数组可以用delete array[2],但这会在下标2的位置产生一个undefined值,长度不变。可以用array.splice(2,1)代替他。
(2)数组和对象的使用时机:
当属性名是小而连续的整数时,你应该使用数组。否则,使用对象。
检测一个对象是否为数组的方法:
1 2 3 4 5 6 7 | var is_array= function (value){ return value&& typeof value=== 'object' && typeof value.length=== 'number' && typeof value.splice=== 'function' && !(value.propertyIsEnumerable( 'length' )); } |
第十章 优美的特性
javascript优美的特性包括:
(1)函数是头等对象:函数是有词法作用域的闭包。
(2)基于原型继承的动态对象:对象是无类别的。我们可以通过普通的赋值给任何一个对象增加一个新成员元素。一个对象可以从另一个对象继承成员元素。
(3)对象字面量和数组字面量:这对创建新的对象和数组来说是一种非常方便的表示法。javascript字面量是数据交换格式JSON的灵感之源。