ES6 class

网友投稿 283 2022-09-04

ES6 class

class基本语法

class Point{ constructor(x,y){ this.x=x; this.y=y; } toString(){ return '('+this.x+','+this.y+')'; } }

类的数据类型就是函数,类本身就指向构造函数,类的所有方法定义在prototype上. Obejct.assign可以方便向类添加多个方法。

class Point{ constructor(){}}Object.assign(Point.protorype,{ toString(){}, toValue(){} })

类的内部所定义的方法,都是不可枚举的。

constructor方法

必须new

类的实例

实例属性除非显示定义在其本身,否则都是定义咋原型上。 类的所有实例共享原型对象。

取值存值函数

class MyClass{ constructor(){ } get prop(){ return 'getter'; } set prop(value){ console.log('setter:'+value); }}let inst = new MyClass();inst.prop = 123;inst.prop;

属性表达式

let methodName='getArea';class Square{ constructor(length){ } [methodName](){ }}

class 表达式

const MyClass = class Me{ getClassName(){ return Me.name; }}

这个Me只能在内部,用不到可以省略

const MyClass = class{}

立即执行的Class

let person=new Class{ constructor(name){ this.name=name; } sayName(){ console.log(this.name); }}("xx");person.sayName();

注意

严格模式,不存在提升,name属性,generator方法

class Point{}Point.nameclass Foo{ constructor(...args){ this.args=args; } *[Symbol.iterator](){ for(let arg of this.args){ yield arg; } }}for(let x of new Foo('hello', 'world')){ console.log(x);}//hello//world

this指向,

class Logger{ printName(name='there'){ this.print(`hello ${name}`); } print(text){ console.log(text) }}const logger = new Logger();const { printName } = logger;printName();//会报错 this会指向该方法运行时所在的环境

解决方法在构造函数中绑定this

class Logger{ constructor(){ this.printName = this.printName.bind(this); }}

另一种解决方法箭头函数

class Obj{ constructor(){ this.getThis = () = > this; }}const myObj=new Obj();myObj.getThis() === myObj;

!!!还有一种解决方法proxy

function selfish(target){ const cache=new WeakMap(); const handler={ get(target,key){ const value=Reflect.get(target,key); if(typeof value !== 'function'){ return value; } if(!cache.has(value)){ cache.set(value,value.bind(target)); } return cache.get(value); } }; const proxy=new Proxy(target,handler);}

静态方法

所有类定义的方法被实例继承,加上static表示直接通过类调用。

class Foo{ static classMethod(){ return "hello";}}Foo.classMethod()var foo=new Foo();foo.classMethod()//错误

如果静态方法包含this,this指的是类

class Foo{ static bar(){ this.baz(); } static baz(){ console.log('hello'); } baz(){ console.log('world'); }}Foo.baz();

子类可以调用父类的静态方法

class Foo{ static classMethod(){ return 'hello'; }}class Bar extends Foo{}Bar.classMethod()

静态方法也可以从super对象调用

class Foo{ static classMethod(){ return 'hello'; }}class Bar extends Foo{ static classMethod(){ return super.classMethod() + ',too'; }}Bar.classMethod()

实例属性新写法

原写法

class IncreasingCounter{ constructor(){ this._count=0; } get value(){ console.log('getting the current value'); return this._count; } increment(){ this._count++; }}class IncreasingCounter{ _count=0; get value(){ console.log('getting the current value'); return this._count; } increment(){ this._count++; }}

这种写法好处,比较整齐

静态属性

class本身的属性Class.propName

class Foo{}Foo.prop=1;Foo.prop

目前只有这种可行,新的提案

class MyClass{ static myStaticProp=42; constructor(){ console.log(MyClass.myStaticProp); }}

这个新写法大大方便静态属性的表达,测试了chrome可以用

class Foo{}Foo.prop=1;新写法class Foo{ static prop=1;}

私有方法和私有属性

有利于代码封装,现有解决方案

//命名上区分class Widget{ foo(baz){ this._bar(baz); } _bar(baz){ return this.snaf=baz; }}

_为只限于内部使用的私有方法,不保险,类的外部也可以调用 另一种移除模块,模块内部的所有方法都是对外可见的

class Widget{ foo(baz){ bar.call(this,baz); }}function bar(baz){ return this.snaf=baz; }

foo是公开的方法,内部调用bar.call(this,baz),使得bar称为当前模块私有方法。 还可以利用symbol唯一性,将私有方法的名字命名为一个Symbol

const bar=Symbol('bar');const snaf=Symbol('snaf');export default class myClass{ foo(baz){ this[bar](baz); } //私有方法提案 [bar](baz){ return this[snaf]=baz; }}

私有属性提案

//#号表示class IncreasingCounter{ #count=0; get value(){ console.log('geting the current value'); return this.#count; } increment(){ this.#count++; }}

在chrome也可以用,也可以用来写私有方法

class Foo{ #a; #b; constructor(a,b){ this.#a=a; this.#b=b; } #sum(){ return #a + #b; } printSum(){ console.log(this.#sum()); }}

不能用 也可以设置getset, 私有属性不限于this引用,只要是在内部,实例也可以引用思域属性

class Foo{ #privateValue=42; static getPrivateValue(foo){ return foo.#privateValue; }}Foo.getPrivateValue(new Foo());

私有属性和方法也可以加static关键字

class FakeMath{ static PI=22/7; static #totallyRandomNumber=4; static #computeRandomNumber(){ return FakeMath.#totallyRandomNumber; } static random(){ console.log('I heard you like random numbers.') return FakeMath.#computeRandomNumber(); }}FakeMath.PIFakeMath.random()

new.target属性

返回new命令作用的那个构造函数,如果构造函数不是通过new或者Reflect.construct()调用

function Person(name){ if(new.target !== undefined){ this.name = name; }else { throw new Error("必须使用new生成实例"); }}//另一种写法function Person(name){ if(new.target ===Person){ this.name = name; }else { throw new Error('必须new'); }}var Person= new Person('1');function person(){}var notAPerson = Person.call(person,'xx');

Class内部调用new.target 返回class

class Rectangle{ constructor(length,width){ console.log(new.target === Rectangle); this.length=length; this.width=width; }}var obj=new Rectangle(3,4);

需要注意,子类继承父类时,new.target返回子类

class Rectangle{ constructor(length,width){ console.log(new.target === Rectangle); }}class Square extends Rectangle{ constructor(length){ super(length,width); }}var obj=new Square(3);

上述代码new.target返回子类,利用这个特点,可以写出不能独立使用,必须继承后使用的类

class Shape{ constructor(){ if(new.target === Shape){ throw new Error('本类不能实例化') } }}class Rectangle extends Shape{ constructor(length,width){ super(); }}var x=new Shape();var y=new Rectangle(3,5);

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:[数据可视化]d3js源码,selection(四)添加事件,控制流,局部变量
下一篇:数据可视化,仿写d3-selection,核心模块选择器(一)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~