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.name

class 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.PI
FakeMath.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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值