今天在看一本書,只有小小的一百多頁,半天快看完半本了,名字叫《學習JavaScript數(shù)據(jù)結(jié)構(gòu)預(yù)算法》.看下來的感受就是,短小精悍,適合復(fù)習一下大學學的數(shù)據(jù)結(jié)構(gòu)。
在讀到使用js實現(xiàn)棧的結(jié)構(gòu)的時候,看到它的寫法是之前的構(gòu)造函數(shù)繼承的寫法,突發(fā)奇想,想用es6的語法改寫一下試試,這是書上的寫法:
function Stack() {
var items = []
this.push = function(element) {
items.push(element)
}
this.pop = function() {
return items.pop()
}
this.peek = function() {
return items[items.length - 1]
}
this.isEmpty = function() {
return items.length === 0
}
this.size = function() {
return items.length
}
this.clear = function() {
items = []
}
this.print = function() {
console.log(items.toString());
}
}
算不上是類的寫法,只是在函數(shù)里定義了幾個方法,去修改items的值而已,新寫的寫法如下:
class Strack {
constructor() {
this.item = []
}
// 棧的壓入
push(value) {
this.item.push(value)
}
// 棧的彈出
pop() {
this.item.pop()
}
// 返回棧頂元素
peek() {
let lengthTemp = this.item.length
return this.item[lengthTemp - 1]
}
// 判空
isEmpty() {
return this.item.length === 0
}
// remove all
clear() {
this.item = []
}
// sum all items
size() {
return this.item.length
}
}
export default Strack
使用:
const newStrack = new Strack()
newStrack.push(1)
newStrack.push(2)
newStrack.push(3)
newStrack.pop()
console.log(newStrack, newStrack);
console.log('newStrack is empty? : ', newStrack.isEmpty());
很簡單,但是沒有弄清楚,這樣寫和以前的寫法有什么的本質(zhì)的區(qū)別,這一點需要去研究一下。
基于類的面向?qū)ο蠛突谠偷拿嫦驅(qū)ο?/h3>
基于類的面向?qū)ο?br>
在基于類的面向?qū)ο笳Z言中(比如Java和C++), 是構(gòu)建在類(class)和實例(instance)上的。其中類定義了所有用于具有某一特征對象的屬性。類是抽象的事物, 而不是其所描述的全部對象中的任何特定的個體。另一方面, 一個實例是一個類的實例化,是其中的一個成員。
基于原型的面向?qū)ο?br>
在基于原型的語言中(如JavaScript)并不存在這種區(qū)別:它只有對象!不論是構(gòu)造函數(shù)(constructor),實例(instance),原型(prototype)本身都是對象?;谠偷恼Z言具有所謂的原型對象的概念,新對象可以從中獲得原始的屬性。
基于類的面向?qū)ο?br> 在基于類的面向?qū)ο笳Z言中(比如Java和C++), 是構(gòu)建在類(class)和實例(instance)上的。其中類定義了所有用于具有某一特征對象的屬性。類是抽象的事物, 而不是其所描述的全部對象中的任何特定的個體。另一方面, 一個實例是一個類的實例化,是其中的一個成員。
基于原型的面向?qū)ο?br> 在基于原型的語言中(如JavaScript)并不存在這種區(qū)別:它只有對象!不論是構(gòu)造函數(shù)(constructor),實例(instance),原型(prototype)本身都是對象?;谠偷恼Z言具有所謂的原型對象的概念,新對象可以從中獲得原始的屬性。
所以,在JavaScript中有一個很有意思的proto屬性(ES6以下是非標準屬性)用于訪問其原型對象, 你會發(fā)現(xiàn),上面提到的構(gòu)造函數(shù),實例,原型本身都有proto指向原型對象。其最后順著原型鏈都會指向Object這個構(gòu)造函數(shù),然而Object的原型對象的原型是null,不信, 你可以嘗試一下Object.prototype.proto === null為true。然而typeof null === 'object'為true。到這里, 我相信你應(yīng)該就能明白為什么JavaScript這類基于原型的語言中沒有類和實例的區(qū)別, 而是萬物皆對象!
封裝
js實現(xiàn)封裝的辦法和java其實差不多
function Person(name) {
this.name = name
var smallName = 'xiaoming'
}
Person. prototype.sayHi = function() {
console.log('hello')
}
上面代碼,定義了一個私有變量smallName和一個方法sayHi,我們并不能通過實例化Person去訪問smallName,還有我們也不知道sayH是怎么實現(xiàn)的,這樣就實現(xiàn)了封裝。
繼承和多態(tài)
在es6以前,我最常使用的繼承方式是使用protutype
function Person(name) {
this.name = name
this.career = function() {
console.log('I am a Person' + name)
}
}
Person.prototype.sayHi = function () {
console.log('my name is ' + this.name);
}
function Teacher(career) {
this.career = function() {
console.log('I am a ' + career + ', my name is ' + this.name)
}
}
Teacher.prototype = new Person('Ma')
Teacher.prototype.constructor = Teacher
var personOne = new Person('Zhang')
personOne.career()
var teaMa = new Teacher('math')
console.log(teaMa);
teaMa.career()
Person是一個父類,子類Teacher想要繼承父類,就在它的prototype指向變?yōu)橐粋€新的父類實例,同時將prototype的constructor屬性指向自己,如果constructor屬性不指回自己的話,將會導(dǎo)致
console.log(teaMa.constructor === Person) // true
這是一個重大錯誤,明明是Teacher實例化出來的,結(jié)果顯示父類實例化的......
新實例化的Teacher有父類的name屬性,這就實現(xiàn)了繼承,同時Person和Teacher類都有career方法,他們通過函數(shù)覆蓋實現(xiàn)了多態(tài)。