今天在看一本书,只有小小的一百多页,半天快看完半本了,名字叫《学习JavaScript数据结构预算法》.看下来的感受就是,短小精悍,适合复习一下大学学的数据结构。
在读到使用js实现栈的结构的时候,看到它的写法是之前的构造函数继承的写法,突发奇想,想用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());
}
}
算不上是类的写法,只是在函数里定义了几个方法,去修改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());
很简单,但是没有弄清楚,这样写和以前的写法有什么的本质的区别,这一点需要去研究一下。
基于类的面向对象和基于原型的面向对象
-
基于类的面向对象
在基于类的面向对象语言中(比如Java和C++), 是构建在类(class)和实例(instance)上的。其中类定义了所有用于具有某一特征对象的属性。类是抽象的事物, 而不是其所描述的全部对象中的任何特定的个体。另一方面, 一个实例是一个类的实例化,是其中的一个成员。 -
基于原型的面向对象
在基于原型的语言中(如JavaScript)并不存在这种区别:它只有对象!不论是构造函数(constructor),实例(instance),原型(prototype)本身都是对象。基于原型的语言具有所谓的原型对象的概念,新对象可以从中获得原始的属性。
所以,在JavaScript中有一个很有意思的proto属性(ES6以下是非标准属性)用于访问其原型对象, 你会发现,上面提到的构造函数,实例,原型本身都有proto指向原型对象。其最后顺着原型链都会指向Object这个构造函数,然而Object的原型对象的原型是null,不信, 你可以尝试一下Object.prototype.proto === null为true。然而typeof null === 'object'为true。到这里, 我相信你应该就能明白为什么JavaScript这类基于原型的语言中没有类和实例的区别, 而是万物皆对象!
封装
js实现封装的办法和java其实差不多
function Person(name) {
this.name = name
var smallName = 'xiaoming'
}
Person. prototype.sayHi = function() {
console.log('hello')
}
上面代码,定义了一个私有变量smallName和一个方法sayHi,我们并不能通过实例化Person去访问smallName,还有我们也不知道sayH是怎么实现的,这样就实现了封装。
继承和多态
在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指向变为一个新的父类实例,同时将prototype的constructor属性指向自己,如果constructor属性不指回自己的话,将会导致
console.log(teaMa.constructor === Person) // true
这是一个重大错误,明明是Teacher实例化出来的,结果显示父类实例化的......
新实例化的Teacher有父类的name属性,这就实现了继承,同时Person和Teacher类都有career方法,他们通过函数覆盖实现了多态。
网友评论