在ES6中增加了class关键字,这对于传统C++程序员来说,无非是更友好的关键字。
传统类定义和class类定义比较:
传统方法中的一种(方法比较多,传统方法比较多,就不一一例举):
function Human( age )
{
this.age = age
this.say =
function()
{
console.log(
"hello, I am ",
this.age ,
"years old!" )
}
}
let h =
new Human(
18)
h.say()
let h2 =
new Human(
20)
h2.say()
输出:
hello, I am 18
years old!
hello, I am 20 years old!
该方式定义类就像是一个函数,因为有function关键字,对于c++程序员来说,总觉得哪里不对。
有了es6标准,一切都变的明朗,下面修改上面类为es6方式
class Human
{
constructor(age)
{
this.age = age
}
say()
{
console.log(
"hello, I am ",
this.age ,
"years old!" )
}
}
let h =
new Human(
18)
h.say()
let h2 =
new Human(
20)
h2.say()
输出:
hello, I am 18
years old!
hello, I am 20 years old!
是不是有了c++的感觉,一看就是定义的一个类。
既然有了类,就涉及到变量的私有化问题,就是在c++中定义类成员变量的public和private问题,那么怎么定义public和private变量呢?不好意思,es6暂不支持私有属性,所有属性默认为public,那我们是不是没有办法使用私有属性呢?我们必须通过es6提供的新特性Symbol来实现。下面给出例子
首先js是以文件为单位,那么一个类常规的写法是定义在一个单独的js文件中,那么新建文件Human.js
单独文件中的class不要忘了export哦,不然外部无法使用,在例子中,可以看出,定义public有两种方式,一种是在任意函数中用this.XXX定义属性,另一种是直接在class内部写XXX,两种方式等价,看个人习惯。定义pravite只需在class外部定义即可。下面是测试代码和输出:
export
default
class Human {
constructor(age) {
this.age = age
//public
this.height =
170
//public
}
hasChild =
false
//public
say() {
this.sex =
"male"
//public
console.log(
"hello, I am ",
this.age,
"years old!")
}
}
测试代码:
import Human
from
'./js/runtime/Human' //该处一定要import
let human =
new Human(
18)
human.say()
console.log(human.age)
console.log(human.sex)
console.log(human.height)
console.log(human.hasChild)
输出结果如下:
hello,I am 18 years old!
18
male
170
false
私有变量例子:
const weight = Symbol(
'weight');//定义Symbol,用于内部私有变量,Symbol的作用自行查资料
export
default
class Human {
constructor(age, w) {
this.age = age
//public
this.height =
170
//public
this
[weight] = w //private
}
hasChild =
false
//public
say() {
this.sex =
"male"
//public
console.log(
"hello, I am ",
this.age,
"years old! I am ", this[weight], "kg")
}
}
测试代码:
import Human
from
'./js/runtime/Human' //该处一定要import
let human =
new Human(
18, 50)
human.say()
console.log(human.age)
console.log(human.sex)
console.log(human.height)
console.log(human.hasChild)
console.log(human.weight)
输出结果如下:
hello,I am 18 years old!I am 50 kg
18
male
170
false
undefined
最后一个human.weight打印undefined,说明外部违法访问到human的weight属性,这样就让weight属性变为私有变量,看到这,你可能有一个疑问,为什么需要使用symbol,而不直接定义一个变量?下面来解释这个问题,在human.js文件中的确可以直接定义一个变量(写在类的外部),外部也没办法访问,但是为什么我们不这样做呢,先看测试代码:
let
weight = 50
export
default
class Human {
constructor(age, w) {
this.age = age
//public
this.height =
170
//public
weight
= w //private
}
hasChild =
false
//public
say() {
this.sex =
"male"
//public
console.log(
"hello, I am ",
this.age,
"years old! I am ", weight , "kg")
}
}
import Human
from
'./js/runtime/Human' //该处一定要import
let human =
new Human(
18, 50)
let
human2 =
new
Human(
18, 55
)
human.say()
console.log(human.age)
console.log(human.sex)
console.log(human.height)
console.log(human.hasChild)
console.log(human.weight)
输出结果如下:
hello,I am 18 years old!I am
55
kg
18
male
170
false
undefined
从输出结果看出,human输出结果55kg,为什么出现这种情况,明明在构造时传入的参数是50。那是因为,默认定义在类外部的变量会处理成static类型,在human2初始化的时候,就把Human中的weight修改为了55,所以说在实例化human2之后在调用human.say(),里面访问到的weight是已经修改过后的值,所以输出55。正因为有这样的特性,在写单例时,可以使用该特性。
使用ES6定义使用函数的方式就比较简单了,在es6中写在class内部的函数(没用function打头)都为public函数,写在类外部的函数(需使用function打头)为类的私有函数。
总结:ES6的class特性看起来也有不好之处,但是个人觉得利大于弊,更符合面向对象的编码规则,除了私有属性不是很好用之外,其他都还ok,比如文中还未提及的继承特性,只需要用extends关键字即可实现继承。并且ES6对私有属性已经有了提案
在之后的标准中,应该会有解决方案。总之个人认为标准更新肯定是为了解决老版本存在的问题,为了更好的发展,所以介意采用新标准。