JavaScript语言的传统方法是通过构造函数定义并生成新对象。下面举个例子。
this.x = x;
this.y = y;
Point.prototype.toString = function(){
return `(${this.x} , ${this.y})`
}
上面这种写法和Java,c++区别很大,这让程序员很困惑。 es6提供了新的语法糖ckass
class Point{
constructor(x,y){
this.x = x;
this.y = y;
}
toString(){
return `(${this.x} , ${this.y})`
}
}
constructor是构造器的方法。而this则代表了该对象。class就是es5的构造函数的另一种写法。更加语义化。
class Point{}
Point === Point.prototype.constructor.Point //true
下面写法也是对等的
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
Point.prototype = {
constructor(){}
toString(){}
toValue(){}
}
而在类的实例上面调用方法,其实就算调用原型上面的方法。
class B{}
let b = new B();
这些方法都是不可枚举的.通过class内部命名的方法,和通过prototype命名的方法最大的不同是一个是可枚举的,另一个是不可枚举的。而添加static关键字的方法会被添加到Point的原型,因此仅仅只可以内部使用。
class Point {
constructor() {
// ...
}
static toString() {
// ...
}
toValue() {
// ...
}
}
class Point1 {}
Point1.prototype = {
constructor() {},
toString() {},
toValue() {},
};
const p = new Point();
const p1 = new Point1();
console.log(Object.keys(Point.prototype));
console.log(Object.keys(Point1.prototype));
console.log(p);
console.log(p1);
console.log(Point.prototype.constructor === Point); // true
console.log(Point1.prototype.constructor === Point1); // true
console.log(Point1.prototype.constructor == Point1); // true
其中虚的是不可枚举的。
这个方法是默认存在的方法,,通过new命令生成对象实例时候自动调用的方法,默认返回它本身这个实例化对象this,当然可以指定返回其他对象。
生成实例对象和es5一样,如果没有new命令,则会报错,除非你在他前面添加static 作为静态方法,就可以。下面可以看到,constructor里面的x,y, 静态aa方法,普通bb方法
class Point {
constructor() {
// ...
this.x = 1;
this.y = 1;
}
static aa() {}
bb() {}
}
const p = new Point();
console.log(p);
console.log(Object.keys(Point.prototype));
new Foo(); // referenceError: Me is not defined class Foo{};
class Foo exntend foo {} 下面介绍super()
class Point {
constructor() {
this.x = 1;
this.y = 1;
}
getname() {
return this.name;
}
}
class ColorPoint extends Point {
constructor() {
super();
this.name = 'ColorPoint';
}
aaa() {
return 'ColorPoint';
}
}
const p = new ColorPoint();
console.log(p);
这里ColorPoint存在两条原型链,一条是继承方法,另一条是继承constructor里面定义的变量。 下面由3钟继承的特殊情况
他代表了父类的实例。
class Point {
constructor() {
this.x = 1;
this.y = 1;
this.name = 'pengliheng';
}
getname() {
return this.name;
}
get prop() {
return this.name;
}
set prop(value) {
console.log(`setter: ${value}`);
}
}
const p = new Point();
p.prop; // setter: pengliheng
p.prop = 'hhhah';
p.prop; // setter: hhhah
class VersionArray extends Array {
constructor() {
super();
this.history=[[]];
}
commit() {
this.history.push(this.slice());
}
revert(){
this.splice
}
}
const a = 'test';
const b = 'test';
a===b // true
const a = {};
const b = {};
a===b // false
const a = [];
const b = [];
a===b // false
[] === [] //false
const a = [];
const b = a;
a===b // true ,为什么呢? 因为point ,a point b
下面看一下他们为什么不相等
class Point {
constructor() {
this.x = 1;
this.y = 1;
this.name = 'pengliheng';
}
static getname() {
return this.name;
}
getTName() {
console.log(new Point() === this);
}
}
console.log(Point.getname()); // 静态方法,不需要实例化就能获取
const p = new Point();
p.getTName(); // false,{} !== {},即便是同样的对象,他们也互不相等。 普通方法需要实例化。
装饰器是一种表达式,他能对类的行为发生改变,,这种改变发生在编译阶段, 有点超前,自己去了解吧,如果你不是用的react或者经常用class面向对象编程,并且需要继承属性的时候,你都用不到装饰器。
####使用 let / constant 替代 var 由于模块化默认使用'use strit'严格模式 所以以后应该是严格模式默认的。 使用优先级 const>let>var const 的使用是因为他是常量,能够给人直观的,如果你要改变常量,建议去定义一个新的常量。这也是函数式编程风格所要求的。 坚持遵循 先声明,再使用的编程规范。
####使用模板字符串添加变量 使用单引号
// bad
const a = '<div>'+value+'</div>'
// good 更具语义化
const a = `<div>${value}</div>`
// bad
var a = 1,b=2,c=3;
//good
const a = 1;
const b = 2;
const c = 3;
// best,,,,,更具语义化。
const [a,b,c] = [1,2,3];
熟悉typescript的你可能知道,它推崇的是尽量使用常量,以及变量+类型 声明了一个对象,尽量不要去改变它,如果真的要改变它,建议使用以下
// bad
const a = {};
a.x = 3;
//
var a = [...arr]; var b = Array.from(arr);
他消灭了 绑定 bind
统一规范编程风格,