类
面向对象oop是业务编程的核心,精通oop等于精通世界万物,无所不能
在JS中,生成实例的传统方法的通过构造函数
而继承往往通过prototype这个对象实现
class
es6的class只是一个语法糖,它的继承模式由es5就可以做到
新的class写法只是让对象原型的写法更加清晰
class A {
constructor(x,y) {
this.x = x
this.y = y
}
toString() {
...
}
}
定义类方法的时候,前面不需要加上function这一个关键字,直接把函数定义放进去就行了
与传统es5的方法一样,类方法函数在prototype上
但要明白的是,class不支持安全模式,必须使用关键字new 创建对象
class A {}
const a = A() // logs TypeError: Class constructor A cannot be invoked without 'new'
与es5不同的时,类的方法(包括构造函数)是不可枚举的,这意味着它不会在for in中出现
class A {
toString() {
console.log('我想搞事情')
}
}
console.log(Object.keys(A.prototype)) // logs []
console.log(Object.getOwnPropertyNames(A.prototype)) // logs [ 'constructor', 'toString' ]
B.prototype.toString = function() {
console.log('BBBBB')
}
console.log(Object.keys(B.prototype)) // logs [ 'toString' ]
console.log(Object.getOwnPropertyNames(B.prototype)) // logs [ 'constructor', 'toString' ]
constutor
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
class A {}
// 等于
class A {
construtor() {}
}
constructor方法默认返回实例对象(即this),当然,你也可以指定返回另外一个对象。
实例
注意 : 在浏览器环境中,浏览器厂商实现了proto的私有属性,该属性会指向实例的原型对象,但不建议在生产环境使用该属性,我们可以使用Object.getPrototypeOf方法获取实例对象的原型
取值函数(getter)和存值函数(setter)
在类的内部可以使用get和set关键字,对某个属性设置存值函数与取值函数 拦截该属性的存储行为
class A {
constructor() { }
get prop() {
return 'getter'
}
set prop(value) {
console.log('setter' + value)
}
}
存值函数与取值函数是设置在属性的Descriptor对象上的
var descriptor = Object.getOwnPropertyDescriptor(
A.prototype, "prop"
);
"get" in descriptor // true
"set" in descriptor // true
属性表达式
类的属性名,可以采用表达式
class A {
constructor(length)
["fuckyou"]() {
}
}
上面的代码中,,Squrae类的方法名为getArea
class表达式
与函数一样,类也可以使用表达式的形式定义。
const MyClass = class Me {
getClassName() {
return Me.name;
}
};
根据这一特性,可以写出立即执行的Class
let a = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('张三');
a.sayName(); // "张三"
注意点
- class默认严格模式
- 暂时性死区,es5构造函数会存在提升现象,而es6不存在提升,这意味着在class定义前会出现暂时性死区
- name,函数具有name属性,es6的class也一样
- 静态方法,class内部用static声明的方法不会被继承,只能通过类名调用,这与java一样
- class中,实例属性可以直接书写
xxx = ''
,而不写在构造函数中,一般用于给实例赋予初始属性而使用
new.target
es6为new命令新增了一个target属性,返回new命令作用域的那个构造函数,如果构造函数没有使用new命令,则该属性为undefined,这优点类似安全模式
我们可以使用这个命令代替安全模式的前置判断
function A(xx) {
if(this instanceof A) {
this.xx = xx
} else {
return new A(xx)
}
}
function A(xx) {
if(new.target === A) {
this.xx = xx
} else {
return new A(xx)
}
}
当然,它的正确使用应该是写抽象类的时候
class A{
constructor() {
if(new.target === A) {
// 抛出错误 : 本类不能实例化
return new TypeError('this is abstract class you must inhert and complete it')
}
}
}
网友评论