您好,登錄后才能下訂單哦!
ES6 的類提供了幾點明顯的好處:
兼容當前大量的代碼。
相對于構造器和構造器繼承,類使初學者更容易入門。
子類化在語言層面支持。
可以子類化內置的構造器。
不再需要繼承庫;框架之間的代碼變得更加輕便。
為將來的高級特性奠定了基礎: traits (或者 mixins ), 不可變實例,等等。
使工具能夠靜態分析代碼( IDE ,類型檢測器,代碼風格檢測器,等等)。
ES6 類掩蓋了 JavaScript 繼承的本質;
類會禁錮你,因為強制性的 new。
function Point(x, y){
this.x = x;
this.y = y;
}
Point.prototype.toString = function(){
return "(" + this.x + "," + this.y + ")";
}
const p = new Point(1,2);
console.log(p);//Point {x: 1, y: 2}
console.log(p.toString());//(1,2)
上面代碼的改用class來寫
class Points {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString(){
return '(' + this.x + ',' + this.y + ')'; }
}
const ps = new Points(1, 2);
console.log(ps);//Points {x: 1, y: 2}
console.log(ps.toString());//(1,2)
ES6的類可以看作構造函數的另一種寫法
class Cty{
//....
}
console.log(typeof Cty);//function
console.log(Cty === Cty.prototype.constructor);//true
//類的數據類型是函數,類本身就指向構造函數
使用的時候,也是直接對類使用new命令,跟構造函數的用法完全一致
class Bar {
doStuff(){
console.log('stuff');
}
}
const b =new Bar();
b.doStuff();//stuff
類的實例上面的方法,其實就是調用原型上的方法
class B {};
const BS = new B();
console.log(BS.constructor === B.prototype.constructor);//true
class Poin{
constructor(x,y){
this.x = x;
this.y = y;
}
toString(){
return `(${this.x},${this.y})`;
}
}
class ColorPoin extends Poin{
constructor(x,y,color){
super(x,y);
this.color = color;
}
toString(){
return super.toString() + " in " + this. color;
}
}
// 類型
console.log(typeof Poin);//function
//news實例
const cp = new ColorPoin(25,8,'green');
console.log(cp.toString());//(25,8) in green
console.log(cp instanceof ColorPoin);//true
console.log(cp instanceof Poin);//true
// instanceof測試構造函數的prototype屬性是否出現在對象的原型鏈中的任何位置
下面是一些方法:
class ObjAssign {
constructor(name, age){
this.name = name;
this.age = age;
}
}
Object.assign(ObjAssign.prototype,{
toString(){
console.log("string");
},
toValue(){
console.log("value")
}
})
const Obj = new ObjAssign('Bob',24);
console.log(Obj);
Obj.toString();//string
Obj.toValue();//value
console.log(Object.keys(ObjAssign.prototype));//["toString", "toValue"]
console.log(Object.getOwnPropertyNames(ObjAssign.prototype));// ["constructor", "toString", "toValue"]
class Pott {
constructor(x,y){
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ',' + this.y + ')';
}
}
const pott = new Pott(2,3);
pott.toString();
console.log(pott.hasOwnProperty("x"));//true
console.log(pott.hasOwnProperty("y"));//true
console.log(pott.hasOwnProperty("toString"));//false
console.log(pott);
console.log(pott.__proto__);
console.log(pott.__proto__.hasOwnProperty("toString"));//true
const p1 = new Pott(2,3);
const p2 = new Pott(3,3);
console.log(p1.__proto__ === p2.__proto__);//true
p1.__proto__.printName = function(){
return "Oops";
}
console.log(p1.printName());//Oops
console.log(p2.printName());//Oops
const p3 = new Pott(4,2);
console.log(p3.printName());//Oops
prop屬性有對應的存值函數和取值函數
class MyClass {
constructor(){
//...
}
get prop(){
return 'getter';
}
set prop(value){
console.log("setter:" + value);
}
}
const inst = new MyClass();
inst.prop = 123;//setter: 123
console.log(inst.prop)//getter
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get html() {
return this.element.innerHTML;
}
set html(value) {
this.element.innerHTML = value;
}
}
const descriptor = Object.getOwnPropertyDescriptor(
CustomHTMLElement.prototype, "html"
);
console.log("get" in descriptor) // true
console.log("set" in descriptor) // true
const MyCl = class Me {
getClassName() {
return Me.name;
}
}
const inMe = new MyCl();
console.log(inMe.getClassName());//Me 只在class內部有定義
const person = new class{
constructor(name){
this.name = name;
}
sayName(){
console.log(this.name);
}
}('張三');
person.sayName();//張三
class Mine {
//...
}
console.log(Mine.name);//Mine
this.printName = this.printName.bind(this)綁定解決
class Logger{
constructor(){
this.printName = this.printName.bind(this);
}
printName(name = 'there'){
this.print(`Hello ${name}`);
}
print(text){
console.log(text);
}
}
const logger = new Logger();
const {printName} = logger;
printName();//Hello there
如果在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承,而是通過類來調用
class Foo{
static classMethod() {
return 'hello';
}
}
console.log(Foo.classMethod());//Hello
const foo = new Foo();
// console.log(foo.classMethod())//foo.classMethod is not a function
class Fun {
static bar(){
this.baz();
}
static baz(){
console.log('hello');
}
baz(){
console.log('world');
}
}
Fun.bar();//hello
父類靜態方法可以被子類調用
class Func{
static classMethod() {
return 'hello';
}
}
class Baa extends Func{
static classMethod(){
console.log(super.classMethod + ",too") ;
}
}
Baa.classMethod();//hello,too
class IncreasingCounter{
// constructor(){
// this._count = 0;
// }
_count = 0;
get value(){
console.log('getting the current value');
return this._count;
}
increment(){
this._count++;
}
}
確保函數只能通過new命令調用
function PersonMan(name){
if(new.target !== undefined){
this.name = name;
}else{
throw new Error('必須使用new命令生成實例')
}
}
function PersonWoman(name){
if(new.target === PersonWoman){
this.name = name;
}else{
throw new Error('必須使用new命令生成實例')
}
}
const personman = new PersonMan('張三');
const personwoman = new PersonWoman('張三');
// const personwoman2 = PersonWoman.call(PersonWoman,'張三');//報錯
內部調用new.target會返回當前的class
class Rectangle{
constructor(length,width){
console.log(new.target);
console.log(new.target===Rectangle);
this.length = length;
this.width = width;
}
}
const rectangle = new Rectangle(3,4);
子類繼承父類時,new.target會返回子類
class Rec{
constructor(length,width){
console.log(new.target);
console.log(new.target===Rectangle);
console.log(new.target===Square);
this.length = length;
this.width = width;
//...
}
}
class Square extends Rec{
constructor(length,width){
super(length,width);
}
}
const squareA = new Square(3,6);//false/true
參考文章
探索ES6
ES6阮一峰
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。