1.创建一个类
在JavaScript中创建一个类,首先声明一个函数保存在一个变量里,然后这个类内部通过对this变量添加属性或方法实现对类添加属性或者方法。
var Book=function(id,bookname,price){
this.id=id;
this.bookname=bookname;
this.price=price;
}
也可以通过类的原型添加属性和方法,有两种方式,一种是为原型对象属性赋值,另一种是将一个对象赋值给类的原型对象。
Book.prototype.display=function(){
//展示这本书
};
//或者
Book.prototype={
display:function(){}
};
//当使用功能和方法时,可以使用new关键字来实例化创建的新对象
var book=new Book(10,'JS',50);
console.log(book.bookname) //JS
2.通过this添加的属性和方法同在prototype中添加的属性和方法有什么区别
通过this添加的属性和方法是在当前对象上添加的,是对象自身拥有的,所以通过类创建一个对象时,this指向的属性和方法都会得到相应的创建。
通过prototype继承的属性或者方法是每个对象通过prototype访问到的,所以每次通过类创建一个新对象时这些属性和方法不会再次创建。
constructor是一个属性,当创建一个函数或者对象时会为其创建一个原型对象prototype,在prototype对象中又会创建一个constructor属性,那么constructor属性指向的就是拥有整个原型对象的函数或对象
3.函数属性和方法的封装
由于js的函数级作用域,声明在函数内部的变量和方法在外界是访问不到的,通过此属性即可创建类的私有变量和私有方法。
在函数内通过this创建的属性和方法,在类创建对象时,每个对象自身都拥有一份并且在外部访问到,通过this创建的属性可以看作是对象共有属性和对象共有方法。不但能够访问这些对象的共有属性和共有方法,而且还能访问类或对象自身的私有属性和私有方法。这类方法称为特权方法。对象创建时特权方法可以初始化实例对象的一些属性,因此创建对象时调用的特权方法还可以看作类的构造器。
var Book=function(id,name,price){
//私有属性
var num=1;
//私有方法
function checkID(){
};
//特权方法
this.getName=function(){};
this.getPrice=function(){};
this.setName=function(){};
this.setPrice=function(){};
//对象的共有属性
this.id=id;
//对象的共有办法
this.copy=function(){};
//构造器
this.setName(name);
this.setPrice(price);
};
通过JavaScript函数级作用域特征实现函数内部创建外界访问不到的私有变量和私有方法。
通过new关键字实例化对象时,由于对类执行一次,所以类的内部this上定义的属性和方法自然可以复制到新创建的对象上,成为对象公有化的属性和方法。
通过new关键字创建新对象时,在类外面通过点语法添加的属性和方法没有执行到,所以新创建的对象无法获取它们,但是可以通过类来使用。因此在类外面通过点语法定义的属性以及方法被称为类的静态共有属性和类的静态共有方法。
类通过prototype创建的属性或方法在类实例对象中可以通过this访问到,所以我们将prototype对象中的属性和方法称为共有属性和共有方法。
//类静态公有属性(对象不能访问)
Book.isChinese=true;
//类的静态公有方法(对象不能访问)
Book.resetTime=function(){
console.log('new Tiem')
};
Book.prototype={
//公有属性
isJSBook:false,
//公有方法
display:function(){}
}
通过new关键字创建对象的实质是对新对象this的不断赋值,并将prototype指向类的prototype所指向的对象。而类的构造函数外通过点语法定义的属性方法不会添加到新创建的对象上去的。要想在新创建的对象中使用isChinese就是通过Book类使用而不能通过this,如Book.isChinese,而类的原型prototype上定义的属性在新对象里可以直接使用,这是因为新对象prototype和类的prototype指向的同一个对象。
var b=new Book(11,'JS',50);
console.log(b.num); //undefined 类的私有属性
console.log(b.isJSBook);//false
console.log(b.id)//11
sonsole.log(b.isChinese)//undefined 类的静态属性
4.闭包
闭包是有权访问另外一个函数作用域中变量的函数,即在一个函数内部创建另外一个函数。将这个闭包作为创建对象的构造函数,这样它既是闭包又是可实例对象的函数,即可访问到类函数作用域中的变量。
var Book=( function (){
//静态私有变量
var bookNum=0;
//静态私有方法
function checkBook(name){}
//创建类
function book(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;
}
)();
5.安全模式
//图书类
var Book=function(title,time,type){
this.title=title;
this.time=time;
this.type=type;
}
//实例化一本书
var book=Book('JavaScript','2014','js');
console.log(book);//undefined
console.log(window.title)//JavaScript
console.log(window.time)//2014
console.log(window.type)//js
new关键字作用可以看作是对当前对象的this不停赋值,然而例子中没有使用new,所以会直接执行这个函数。而这个函数是在全局作用域中执行了,this指向全局变量,所以属性自然添加到window上面了。
安全模式
//图书类
var Book=function(title,time,type){
//判断执行过程中this是否是当前这个对象
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');