1,javascript函数基础
1.1 JavaScript中定义一个函数
function fu(){}
1.2 函数的另一种形式
var fu = function(){};
第二种函数与第一种函数定义的区别, 第二种,先在作用域中声明fu变量, 再对变量赋值, 第一种在声明的同时就赋值了
1.3 用对象收编变量
var CheckObject = {
checkName:function(){
...
},
checkEmail:function(){
...
},
checkPassword:function(){
...
}
}
1.4 对象的另一种形式
向对象中添加方法
var checkObject = function(){};
checkObject.checkName = function(){
...
}
1.5 真假对象
使用函数将对象封装起来,每次调用的时候返回子的新对象。
var CheckObject = {
return{
checkName:function(){
...
},
checkEmail:function(){
...
},
checkPassword:function(){
...
}
}
}
1.6 使用类的方法封装
var CheckObject = function(){
this.checkName:function(){
...
},
this.checkEmail:function(){
...
},
this.checkPassword:function(){
...
}
}
注意使用类的方式封装的时候,调用需要先定义对象。
var a = new checkObject();
a.checkName();
1.7 一个检测类
在上面的类封装方法中,每新建一个对象,都会从CheckObject作用域中复制全部方法到新对象中(比如上面的a),当new很多新的对象时,这种开销会很大,可以使用下面的方法,使所有CheckObject方法创新的对象共用一个方法。
var CheckObject = function(){}
CheckObject.prototype = {
checkName:function(){
...
},
checkEmail:function(){
...
},
checkPassword:function(){
...
}
}
1.8 将对象作为返回值
var CheckObject = function(){
checkName:function(){
...
return this;
},
checkEmail:function(){
...
return this;
},
checkPassword:function(){
...
return this;
}
}
简化重复调用时创建新对象的损失
CheckObject.checkName().checkEmail().checkPassword();
1.9 函数的祖先
使用prototype给每个函数添加checkEmail方法
Function.prototype.checkEmail = function(){
...
}
1.10 使用链式方法添加
Function.prototype.addMethod = function(name,fn){
this[name] = fn;
return this;
}
var methods = function(){};
methods.addMethod('checkName',funciton(){}).addMethod('checkEmail',funciton(){})
2,面向对象编程
2.1 面向过程编程和面向对象编程
面向过程编程主要是流程式编程,面向对象编程在于封装的艺术,此外还有多态,继承之类就不说了...
2.2 封装
2.2.1 JavaScript中创建一个类
var Book = function(id,bookname,price){
this.id = id;
this.bookname = bookname;
this.price = price;
}
使用prototype扩展类原型
Book.prototype.display = function(){
...
}
2.2.2 属性方法与封装
JavaScript中定义一个一般类如下,
var Book = function(id,name,price){
//私有属性
var num =1;
//私有方法
function checkID(){
...
};
//特权方法
this.getName = function(){};
this.getPrice = function(){};
this.setNam = function(){};
this.setPrice = function(){};
//对象公有属性
this.id=id;
//对象公有方法
this.copy = function(){};
//构造器
this.setName(name);
this.setPrice(price);
}
使用prototype创建类的共有属性和共有方法(如上所述,这个属性和方法类的所有实例共享)
//类静态共有属性(对象不能访问)
Book.isChinese = true;
//类静态公有方法(对象不能访问)
Book.resetTime = function(){
console.log('New Time')
};
Book.prototype = {
//公有属性
isJSBook : false,
//公有方法
display : function(){
}
}
2.2.3 闭包实现
将类的静态变量通过闭包实现
//利用闭包实现
var Book = (function(){
//静态私有变量
var bookNum = 0;
//静态私有方法
function checkBook(name){
}
//返回构造函数
return function(newId,newName,newPrice){
//私有变量
var name,price;
//私有方法
function checkID(id){}
//特权方法
this.getName = function(){};
this.getPrice = function(){};
this.setName = function(){};
this.setPrice = function(){};
//公有属性
this.id = newId;
//公有方法
this.copy = function(){};
bookNum++
if(bookNum>100)
throw new Error('我们仅出版100本书');
//构造器
this.setName(name);
this.setPrice(price);
}
})();
Book.protottype = {
//静态公有属性
isJSBook:false,
display : function(){}
};
将prototype构建原型放在闭包内
//利用闭包实现
var Book = (function(){
//静态私有变量
var bookNum = 0;
//静态私有方法
function checkBook(name){
}
//返回构造函数
return function(newId,newName,newPrice){
//私有变量
var name,price;
//私有方法
function checkID(id){}
//特权方法
this.getName = function(){};
this.getPrice = function(){};
this.setName = function(){};
this.setPrice = function(){};
//公有属性
this.id = newId;
//公有方法
this.copy = function(){};
bookNum++
if(bookNum>100)
throw new Error('我们仅出版100本书');
//构造器
this.setName(name);
this.setPrice(price);
}
//构建原型
_book.prototype = {
//静态公有属性
isJSBook:false;
//静态公有方法
display:function(){}
};
//返回类
return _book;
})();
2.2.4 创建对象的安全模式
防止在创建对象时 未申请作用域就直接创建对象,这样this会指向全局作用域,本来赋予对象作用域的属性和方法就会被赋予到全局作用域中
//图书安全类
var Book = function(title,time,type){
//判断执行过程中this是否指向当前这个对象(如果是说明用new创建的)
if(this instanceof Book){
this.title = title;
this.time = time;
this.type = type;
//否则重新创建这个对象
}else{
return new Book(title,time,type);
}
}
这样使用下面的这种方法新建一个对象就不会使变量污染到全局作用域中
var book = Book('javascript','2014','js');
2.3 继承
2.3.1 原型继承—类式继承
//类式继承
//声明父类
function SuperClass(){
this.superValue = true;
}
//为父类添加公有方法
SuperClass.prototype.getSuperValue = function(){
return this.superValue;
};
//声明子类
function SubClass(){
this.subValue = false;
}
//继承父类
SubClass.prototype = new SuperClass();
//为子类添加共有方法
SubClass.prototype.getSubValue = function(){
return this.subValue;
};
类式继承的缺点,无法向父类传参
2.3.2 构造函数继承
//构造函数式继承
//声明父类
function SuperClass(id){
//引用类型公有属性
this.books = ['javascript','xiaobaicai','1000'];
//值类型共有属性
this.id = id;
}
//父类声明原型方法
SuperClass.prototype.showBooks = function(){
consle.log(this.books);
}
//声明子类
function SubClass(id){
//继承父类
SuperClass.call(this,id);
}
在构造函数中,使用SuperClass.call(this,id)语法通过将父类作用域中的属性和方法在子类作用域中执行一遍(将父类作用域中的属性复制到子类作用域中),这种方式,在继承的过程中,SuperClass.prototype.showBooks 属性也复制到了子类作用域中,即子类中也有公有属性 showBooks 而且子类中的这个属性指针是指向子类作用域中的。父类中也同样与公有属性showBooks。但是在我们原设计中,子类的showBooks 方法和父类的showBooks方法应该是指向同一个showBooks的。
2.3.3 组合继承
//组合式继承
//声明父类
function SuperClass(name){
//值类型公有属性
this.name = name;
//引用类型公有属性
this.books = ["html","css","JavaScript"]
}
//父类原型公有方法
SuperClass.prototype.getName = function(){
console.log(this.name);
};
//声明子类
function SubClass(name,time){
//构造函数式继承父类name属性
SuperClass.call(this,name);
//子类中新增公有属性
this.time = time;
}
//类式继承 子类原型继承父类
SubClass.prototype = new SuperClass();
//子类原型方法
SubClass.prototype.getTime = function(){
console.log(this.name);
};
2.3.4 原型继承
根据已有的对象创建一个新对象
//原型式继承
function inheritObject(o){
//声明一个过渡函数对象
function F(){}
//过渡对象的原型继承父对象
F.prototype = o;
//返回过渡对象的一个实例,该实例的原型继承了父对象
return new F();
}
2.3.5 寄生式继承
//寄生式继承
//声明基对象
var book = {
name:"js book",
alikeBook:["css book","html book"]
};
function createBook(obj){
//通过原型继承方式创建新对象
var o = new inhertObject(obj);
//拓展新对象
o.getName = function(){
console.log(name);
};
//返回拓展后的新对象
return o;
}
寄生式继承实质上是对原型继承的二次封装
2.3.6 寄生组合式继承
/**
*寄生式继承 继承原型
*传递参数 subClass 子类
*传递参数 superClass 子类
**/
function inheritPrototype(subClass,superClass){
//复制一份父类的原型副本保存在变量中
var p = inheritObject(superClass.prototype);
//修正因为重写子类原型导致子类的constructor属性被修改
p.constructor = subClass;
//设置子类的原型
subClass.prototype = p;
}
2.4 多继承
先看一个继承单对象属性的extend方法
//单继承 属性复制
var extend = function(target,source){
//遍历源对象中的属性
for(var property in source){
//将源对象中的属性复制到目标对象中
target[property] = source[property];
}
//返回目标对象
return target;
};
扩展上面的函数实现多继承
//多继承 属性复制
var min = function(){
var i = 1; //从第二个参数起为被继承的对象
var len = arguments.length; //获取参数长度
var target = arguments[0]; //第一个对象为目标对象
var arg; //缓存参数对象
//遍历被继承的对象
for(;i<len;i++){
//缓存当前对象
arg = arguments[i];
//遍历被继承对象中的属性
for(var property in arg){
//将继承对象中的属性复制到目标对象中
target[property] = arg[property];
}
}
//返回目标对象
return target;
};
mix方法的作用将传入的多个对象的属性复制到源对象中,这样即可实现对多个对象的属性的继承。
下面是将min方法绑定到原生对象Object上。
Object.prototype.mix = function(){
var i = 1;
var len = arguments.length;
var arg;
for(;i<len;i++){
//缓存当前对象
arg = arguments[i];
//遍历被继承对象中的属性
for(var property in arg){
//将继承对象中的属性复制到目标对象中
target[property] = arg[property];
}
}
}
2.5 多态
下面是一个实现多态的例子
//多态
function add(){
//获取参数
var arg = arguments;
//获取参数长度
var len = arg.length;
switch(len){
//如果没有参数
case 0:
return 10;
//如果只有一个参数
case 1:
return 10 + arg[0];
//如果有两个参数
case 2:
return arg[0]+arg[1];
}
}
一种更简单易懂的写法
function Add(){
//无参数算法
function zero(){
return 10;
}
//一个参数算法
function one(num){
return 10 + num;
}
//两个参数算法
function two(num1,num2){
return num1+num2;
}
//相加共有方法
this.add = function(){
var arg = arguments;
var len = arg.length;
switch(len){
//如果没有参数
case 0:
return zero();
//如果只有一个参数
case 1:
return one(arg[0]);
case 2:
return two(arg[0],arg[1]);
}
}
}
3,总结
这篇文章简单的总结了一下JavaScript中管理不同作用域中的方法,如使用函数作用域封装起来。和JavaScript中面向对象的特性,主要是JavaScript中多种继承方式。还是很基础的。