第一章 序
1.1 JS的灵活性
支持多种不同编程风格。函数式编程风格,面向对象编程风格
1.2 弱类型语言
弱类型≠没有类型
原始类型:Boolean,Number,String
原始数据类型按值传送,其他数据类型按引用传送
不同类型之间可以相互转换
1.3 函数是一等对象
可以存储在变量中,
可以作为参数传给其他函数,
可以作为返回值从其他函数传出
可以在运行时进行构造
闭包 把变量保存在闭包中,对其加以保护
js具有函数级作用域,定义在函数内部的变量在函数外部不能访问
js作用域是词法性质的,函数运行在定义它的作用域,不是调用它的作用域
1.4 对象的易变性
一切都是对象(即使是原始类型,在必要的时候会包装为对象),对象都是易变的
易变性:可以对函数,先前定义的类和实例化的对象进行修改
第二章:接口
js中没有内置的方法创建或实现接口,也没有内置的方法判断一个对象是否实现了与另一个对象相同的一套方法
接口:提供一种用以说明一个对象应该具有哪些方法的手段
接口结构包含的信息:需要实现什么方法,这些方法应该有哪些参数
js模仿接口
1. 注释法
把需要实现的接口放在注释里面,属于程序文档范畴
不能实现强制性要求,不实现也不会报错
不提供错误信息,对调试和测试没有帮助
2. 使用属性检查模仿接口
在下面的代码中,CompositeForm显式声明自己实现了xxx,xxx接口,将实现接口的名称加入名为implementsInterfaces数组。
强制性要求程序员声明实现的接口,但是,不能确保程序员真正实现了自称实现的接口。
//interface Composite 方法:add,remove,getChild
//interface FormItem 方法:save
let CompositeForm=function(id,method,action){
//显示声明自己实现了哪些接口
this.implementsInterfaces=['Composite','FormItem'];
...
}
//调用implements函数
function addForm(formInstance){
if(!implements(formInstance,'Composite','FormItem')){
throw new Error(`${formInstance}没实现Composite,FormItem接口`);
}
...
}
//检查是否实现了某些接口
function implements(...argus){
//argus 待检测的类 实现接口1 实现接口2...
let obj=argus[0];
for(let i=1;i<argus.length;i++){
let interfaceName=argus[i];
let interfaceFound=false;
for(let j=0;j<obj.implementsInterfaces.length;j++){
if(obj.implementsInterfaces[j]==interfaceName){
interfaceFound=true;
break;
}
}
if(!interfaceFound) return false;
}
return true;
}
3. 使用鸭式辨型模仿接口
类是否声明自己实现了哪些接口不重要,重要的是具有接口中的方法。
如果对象具有与接口定义的方法同名的所有方法,就认为对象实现了这个接口。
缺点:
1.类不声明自己实现了哪些接口,降低了代码的可重用性。
2.缺少自我描述
3.需要借助辅助类(Interface)和辅助函数(ensureImplements)
//Interfaces
let Composite =new Interface('Composite',['add','remove','getChild']);
let FormItem=new Interface('FormItem',['save']);
//CompositeForm class
let CompositeForm=function(id,method,action){
...
};
...
//检查类有没有实现接口对应的方法
function addForm(formInstance){
Interface.ensureImplements(formInstance,Composite,FormItem);
}
//Interface类
let Interface=function(name,methods){
if(arguments.length!= 2){
throw new Error(`${name}接口应该只有两个参数`);
}
this.name=name;
this.methods=[];
for(let i=0,len=methods.length;i<len;i++){
if(typeof methods[i] !== 'string'){
throw new Error(`接口方法${method[i]}名字应该是字符串`)
}
this.methods.push(methods[i]);
}
}
//ensureImplements
Interface.ensureImplements=function(...argus){
if(argus.length<2){
throw new Error('参数至少是两个');
}
let obj=argus[0];
for(let i=1;i<argus.length;i++){
let interface=argus[i];
if(interface.constructor!==Interface){
throw new Error(`${interface}必须是Interface实例`)
}
for(let j=0,len=interface.methods.length;j<leln;j++){
let method=interface.method[j];
if(!object[method] || typeof obj[method]!=='function'){
throw new Error(`没有实现${method}方法`);
}
}
}
}
第三章 封装和信息隐藏
25