JavaScript是一门面向对象的语言,要理解面向对象,就一定要先理解面向对象之前的变成方式——面向过程。
面向过程的代码其实对于小白程序员一点也不陌生,学习一门语言,特别是在学完function之后,每个人都会别写大量的面向过程的代码。面向过程说白了就是按照解决问题 的流程,声明一堆方法,然后调用方法解决问题。
那面向对象呢?面向对象就是/*将你的需求抽象成一个对象那个,然后针对这个对象分析其特征(属性)与动作(方法),以上都是屁话,所以注释掉。*/先创建对象,然后调用对象的方法来解决问题。为啥要这么做?声明函数然后调用不是挺好的吗?先举个简单的例子:你要搬家,你家有1000个东西(衣服袜子内裤拖鞋洗漱用品电子产品书床上用品套套各种卡,你敢说你家没1000件东西?),你会一件一件的搬还是将他们打包后再搬?你搬家这样,写代码也是这样。
下面说正事,先讲讲创建对象的n种方式:直接量、new Object、构造函数(类)。。。。。。
但是用的最多的还是构造函数(类)方式,为啥?第一,因为别的语言都是这么写的。。第二:因为它好用,用好了可以实现封装和继承。
假如你还不会使用构造函数,或者没听说过啥叫封装和继承,请自行离开去百度,然后请过一段时间再回来,因为下面的内容可能不太适合你,会引起的你一些不适。
今天,咱们来好好唠唠封装和继承的高级用法。。。
封装,说白了就是声明构造函数(声明类)
提示:下面构造函数我会用‘类’来代替,为啥?因为类就一个字,我只说一次。。。
先来看看类的私有属性和共有与属性:
function Book(name){
//私有属性/方法
var num=1;
//共有属性/方法
this.getName=function(){console.log(name)};
//特权方法 能够操纵私有属性、方法
this.getNum=function(){console.log(num)};
this.setNum=function(n){num=n};
}
var b=new Book('html5')
console.log(b.num); //undefined
再来看看共有属性和/方法、类静态共有属性/方法:
function Book(name){
//私有属性/方法
var num=1;
//共有属性/方法
this.getName=function(){console.log(name)};
//特权方法 能够操纵私有属性、方法
this.getNum=function(){console.log(num)};
this.setNum=function(n){num=n};
}
//类静态共有属性 (对象不能访问)
Book.isChinese=true;
//类静态共有方法 (对象不能访问)
Book.resetTime=function(){
console.log(new Date());
};
Book.prototype={
//共有属性
isJSBook:true,
//共有方法
display:function(){}
};
var b=new Book('JavaScript');
console.log(b.num); //undefined
console.log(b.isJSBook); //true
console.log(b.isChinese); //undefined
共有属性/方法用于创建对象后调用。类静态属性和方法对象不能调用,但类可以(类是个函数,函数是个对象,对象就有属性和方法,没听过?那你听说过构造函数的prototype属性吧?)。私有属性/方法一般是不想被修改的,但为了获取他们都留有特权方法。
接下来,咱们来看看闭包实现私有属性的方式一:
var Book=(function(){
//静态私有变量
var bookNum=0;
//返回构造函数
return function(id,name,price){
//私有变量
var name,price;
//特权方法
this.getName=function(){};
this.setName=function(){};
//公有属性/方法
this.id=id;
this.copy=function(){};
//调用 静态私有变量
bookNum++;
if(bookNum>100){throw new Error('我们仅出版100本书')}
}
})();
//类静态共有属性 (对象不能访问)
Book.isChinese=true;
//类静态共有方法 (对象不能访问)
Book.resetTime=function(){
console.log(new Date());
};
Book.prototype={
//共有属性
isJSBook:true,
//共有方法
display:function(){}
};
var b=new Book('JavaScript');
console.log(b.bookNum); //undefined
console.log(b.isJSBook); //true
console.log(b.isChinese); //undefined
闭包实现私有属性的方式二——直接返回一个完整的类:
var Book=(function(){
//静态私有变量
var bookNum=0;
//返回构造函数
function _book(id,name,price){
//私有变量
var name,price;
//特权方法
this.getName=function(){};
this.setName=function(){};
//公有属性/方法
this.id=id;
this.copy=function(){}
//调用 静态私有变量
bookNum++;
if(bookNum>100){throw new Error('我们仅出版100本书')}
}
//类静态共有属性 (对象不能访问)
_book.isChinese=true;
//类静态共有方法 (对象不能访问)
_book.resetTime=function(){
console.log(new Date());
};
_book.prototype={
//共有属性
isJSBook:true,
//共有方法
display:function(){}
};
return _book;
})();
var b=new Book('JavaScript');
console.log(b.bookNum); //undefined
console.log(b.isJSBook); //true
console.log(b.isChinese); //undefined
最后,因为很多小白用户在实例化对象(挺牛逼是不?其实就是通过new创建对象啦)时老实忘记写new,所以我们来了解一下封装的安全模式:
function Book(name){
//判断 执行时 this 是否指向 当前对象
//如果是 说明是 new 创建的
if(this instanceof Book){
this.name=name;
//否则创建新对象
}else{
return new Book(name);
}
}
var h=new Book('html5');
var j=Book("JavaScript")
console.log(h.name);
console.log(j.name);
最最后,是关于向类的原型(构造函数的prototype)中链式添加方法和链式操作的小技巧:
//在Function 的 prototype 中 添加方法addMethod
//方法有两个参数 方法名 和 方法
Function.prototype.addMethod=function(name,fn){
//将 第二个参数方法 放入 调用本方法 的 对象的 prototype 中 ,名字为第一个参数方法名
this.prototype[name]=fn;
return this;//返回this 为了链式添加
};
//声明一个构造函数
var methods=function(){};
//调用 function 的 addMethod 方法,向 methods 中添加方法
methods.addMethod('checkName',function(){
//验证用户名 的代码
console.log('check 用户名')
return this; //返回this 为了能够链式操作
}).addMethod('checkEmail',function(){
//验证邮箱 的代码
console.log('check 密码')
return this; //返回this 为了能够链式操作
});
//实例化 methods 类
var a=new methods;
a.checkName().checkEmail()
关于面向对象中封装的技巧就向大家介绍到这里,下一篇会向大家介绍面向对象中继承的一些小技巧