面向对象编程就是将你的需求抽象成一个对象,然后针对这个对象分析器特征(属性)与动作(方法)。这个对象我们称之为类。 面向对象编程思想其中有一个特点就是封装。
在ES5中创建一个类很容易,首先声明一个函数保存在一个变量里(变量名首字母大写),在这个函数(类)的内部通过this(函数内部自带的一个变量,用于指向当前这个对象)变量添加属性或者方法来实现对类添加属性或者方法
var Book = function(id,bookName,price){
this.id = id;
this.bookName = this.bookName;
this.price = price;
}
也可以通过在类(类也是一个对象,所以也有原型)的原型上添加属性和方法。
1.一一为原型对象属性赋值
Book.prototype.display = function(){};
2.将一个对象赋值给类的原型对象
Book.prototype = {
display: fnction(){}
}
var book = new Book(1,'javascript',55);
console.log(bookName) //javascript
通过this添加的属性和方法 与 在prototype中添加的属性和方法有什么区别?
通过this添加的属性和方法是在当前对象上的,然而Javascript是一种基于原型prototype的语言,所以每创建一个对象时(在javascript中函数也是一种对象),它都有一个原型prototype用于指向其继承的属性和方法。这样通过prototype继承的方法并不是对象自身的,所以在使用这些方法时,需要通过prototype一级一级的查找来得到,这样你就会发现通过this定义的属性或者方法是该对象自身拥有的,所以每创建一个新的对象时,this指向的属性和方法都会得到相应的创建,而通过prototype创建的属性或者方法是每个对象通过prototype访问到,所以通过类创建一个新对象时这些属性和方法不会再次创建。
原型对象prototype
constructor是一个属性,当创建一个函数或者对象时都会为其创建一个原型对象prototype,在prototype对象中又会像函数中创建this一样创建constructor属性,那么constructor属性指向的就是拥有整个原型对象的函数或者对象。
属性与方法的封装
私有属性,私有方法,共有属性,共有方法,保护方法等等
由于Javascript的函数级作用域,声明在函数北部的变量以及方法在外界是访问不到的,通过此特性创建类的私有变量以及私有方法。
在函数内部通过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 关键字实例化对象时,执行了一遍类的函数,所以通过特权方法自让可以初始化对象的一些属性了。
问题1. 在类的外部通过点语法定义的属性和方法以及在外部通过prptotype定义的属性和方法有什么作用?
通过new关键字创建新对象时,由于类外面通过点语法添加的属性和方法没有执行到,所有新创建的对象中无法获取他们,但是可以通过类来使用。因此在类外面通过点语法定义的属性和方法被称为类的静态共有属性和类的静态方法。而通过prototype创建的属性或者方法在类实例的对象中是可以通过this访问到的,所以我们将prototype对象中的属性和方法称之为共有属性和共有方法。
//类静态共有方法(对象不能访问)
Book.isChinese = true;
//类静态共有方法(对象不能访问)
Book.resetTime = function(){}
Book.portotype = {
//公有属性
isJSBook: false,
//公有方法
display: function(){}
}
通过new关键字创建的对象实质上是对新对象this的不断赋值,并将prototype指向类的prototype所致的对象那个,而类的构造函数外面通过点语法添加定义的属性方法是不会添加到新创建的对象上去的。因此要想在新创建的对象中使用isChinese就得通过Book类使用而不是通过this。而类的原型prototype上定义的属性在新对象里可以之恶极使用,这是因为新对象prototype和类执行的是同一个队象。
var b = new Book(11,'javascript',50);
console.log(b.num) // undefined
console.log(b.isJSBook) //true
console.log(b.id) //11
console.log(b.isChinese) //undefined
类的静态公友属性可以通过类的自身访问
console.log(Book.isChinese) //true
Book.resetTime() //
闭包实现
闭包是有权访问另一个函数作用域中变量的函数,即在一个函数内部创建另一个函数。
var Book = (function(){
//静态私有变量
var bookNum = 0;
//静态私有方法
function checkBook(){
}
//返回构造函数
function _book(newId,newName,newPrice){
//私有变量
var name = newName;
var price = newPrice;
//私有方法
function checkId(id){}
//特权方法
this.getName = function(){}
this.getPrice = function(){}
this.setName = function(){
console.log(name)
}
this.setPrice = function(){}
//公有属性
this.id = newId;
//公有方法
this.copy = function(){}
bookNum++
if(bookNum>2){
throw new Error('仅剩一本')
}
this.setName(name)
this.setPrice(price)
}
//构造原型
_book.prototype = {
isJSBook: false,
display: function(){}
}
//返回类
return _book
})()
var b = new Book(1,"javascript",11)
console.log(b.isJSBook)
//创建对象的安全模式
new关键字的作用可看作是对当前的对象的this不停的赋值。如果没有new,this的指向就会指向全局作用域。
var Book = function(id,name){
//判断执行过程中this是否是当前这个对象(这里说明是用new创建的)
if(this instanceof Book){
this.id = id
this.name = name
//否则重新创建对象
}esle{
return new Book(id,name)
}
}
var book = Book(1,"javascript")
每个类都有三个部分
1. 构造函数内的,这是供实例化对象复制用的,
2.构造函数外的,直接通过点语法添加的,这是供类使用的,实例化对象是访问不到的。
3.是类的原型中的,实例化对象可以通过其原型链间接的访问到,也是为供所有实例化对象所共用。