ES6学习笔记(一)class类
2018-12-04 本文已影响0人
大大大大大西瓜G
一:ES5中的仿类
JS在ES5及更早版本中都不存在类,与类最接近的是:创建一个构造器,然后将方法指派到该构造器的原型上。这种方式通常被称为创建一个自定义类型,例如:
function PersonType(name) {
this.name = name ;
}
PersonType.prototype.sayName = function() {
console.log(this.name);
}
let person = new PersonType('张三');
person.sayName(); // 输出 '张三'
console.log(person instanceof PersonType); // true
console.log(person instanceof Object); // true
// 此代码中 PersonType 是一个构造函数,并创建了单个属性name。
// sayName() 方法被指派到原型上,因此在 PersonType 对象的所有实例上都共享了此方法
// 接下来使用 new 运算符创建了 PersonType 的一个新实例 person ,此对象会被认为是一个通过原型继承了 PersonType 与 Object 的实例
二:ES6中class类的基本用法
ES6引入了Class(类)这个概念,作为对象的模板,通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。【它看起来很想其它语言中的类】。上面的代码用ES6的“类”改写,就是下面这样。
class PersonClass {
// 等价于 personType 构造器
constructor(name) {
this.name = name;
}
// 等价于 personType .prototype.sayName
sayName() {
console.log(this.name)
}
}
let person = new PersonClass('李四');
person.sayName(); // 输出 '李四'
console.log(person instanceof PersonClass); // true
console.log(person instanceof Object); // true
console.log(typeof PersonClass); // 'function'
console.log(typeof PersonClass.prototype.sayName); // 'function'
这个PersonClass类声明的行为非常类似上例中的PersonType,类声明允许你在其中使用特殊的 constructor 方法名称直接定义一个构造器,而不需要线定义一个函数再把它当做构造器使用。由于类的方法使用了简写语法,于是就不再需要使用 “function” 关键字。
三:为何要使用类语法
尽管类与自定义类型之间有相似性,但仍然要记住一些重要的区别:
1. 类声明不会被提升,这与函数定义不同,类生命的行为与let相似,因此程序在执行到达圣明厨之前,类会存在于暂时性死区内;
2. 类声明中的所有代码会自动运行在严格模式下,并且无法退出严格模式;
3. 类的所有方法都是不可枚举的,这是对于自定义类型的显著变化,后者必须用Object.defineProperty()才能将方法改变为不可枚举;
4.类的所有方法内部都没有 [[constructor]] ,因此使用 new 来调用它们会抛出错误;
5.调用类构造器时不适用 new 关键字,会抛出错误;
6.试图在类的方法内部重写类名,会抛出错误;
因此,上例中的PersonClass声明实际上就直接等价于以下未使用类语法的代码
// 直接等价于 PersonClass
let PersonType2 = (function() {
"use strict" ;
const PersonType2 = function(name) {
// 确认函数被调用时使用了 new
if (typeof new.target === "undefined") {
throw new Error('constructor 构造器必须要使用new 关键字调用!')
}
this.name = name;
}
Object.defineProperty(PersonType2.prototype,'sayName',{
value: function() {
// 确认函数被调用时没有使用 new
if (typeof new.target !== "undefined") {
throw new Error('方法不能被 new 调用')
}
console.log(this,name);
},
enumerable : false,
writable : true,
configurable : true
});
retuen PersonType2;
}())
代码讲解:
首先要注意这里有两个PersonType2声明:一个在外部作用域的let声明,一个在内部的const声明,这就是为何类的方法不能对类名称进行重写、而类外部的代码则被允许。构造函数检查了 new.target,以保证被调用时使用了 new ,否则就抛出错误。接下来,say.Name()方法被定义为不可枚举。并且此方法也检查了 new.target ,它则要保证在被调用时没有 new 。最后一步是将构造函数返回出去。
QQ图片20181112170456.jpg尽管不适用新语法也能实现类的任何特性。但类语法显著简化了所有功能的代码!