面向對象編程就是將你的需求抽象成一個對象,而後針對這個對象分析器特徵(屬性)與動做(方法)。這個對象咱們稱之爲類。 面向對象編程思想其中有一個特色就是封裝。javascript
在ES5中建立一個類很容易,首先聲明一個函數保存在一個變量裏(變量名首字母大寫),在這個函數(類)的內部經過this(函數內部自帶的一個變量,用於指向當前這個對象)變量添加屬性或者方法來實現對類添加屬性或者方法java
var Book = function(id,bookName,price){編程
this.id = id;安全
this.bookName = this.bookName;閉包
this.price = price;函數
}this
也能夠經過在類(類也是一個對象,因此也有原型)的原型上添加屬性和方法。spa
1.一一爲原型對象屬性賦值prototype
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.是類的原型中的,實例化對象能夠經過其原型鏈間接的訪問到,也是爲供全部實例化對象所共用。