1 class简介
通过传统的构造函数生成对象
function Point({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
Point.prototype.toString = function () {
return `${this.name},${this.age},${this.tall}`
}
const Point1 = new Point({name:"张三" , age:24, tall:173});
console.log(Point1);
console.log(Point1.toString());
Point { name: '张三', age: 24, tall: 173 }
张三,24,173
es6 通过class关键字创建对象
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
const Point4 = new Point2({name:"小张" , age:20, tall:180});
console.log(Point4);
console.log(Point4.toSoring());
Point2 { name: '小张', age: 20, tall: 180 }
小张,20,180
通过class创建的类里面存在一个constructor构造方法。this关键字代表实利对象。 简而言之es5的Point构造代表es6中Point的构造方法, Point除了构造方法之外还定义了toSoring方法。 值得注意的是在定义类的方法时是不需要加function关键字的直接定义函数即可。此外方法与方法之间是不需要加逗号分隔的,
es6的类可以看到是构造函数的另一种写法。即类的数据类型本身就是函数。而类本身指向构造函数
console.log(typeof Point2);
console.log(typeof Point2 === typeof Point2.prototype.constructor);
function
true
构造函数的prototype属性在es6上仍然存在。 实际上类的所以上传都是定义在类的prototype上。
class Point5 {
constructor({}){}
toSoring(){}
}
// 等同于
Point5.prototype = {
constructor(){},
toSoring(){}
};
在实利上调用方法就是在原型上调用方法
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
console.log(Point4.toSoring === Point2.prototype.toSoring)
true
由于类的方法都定义在prototype上。故可以通过Object.assign()一次性添加多个新的方法
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
Object.assign(Point2.prototype,{
toValue(){
return this.name
},
getAge(){
return this.age
}
})
const Point4 = new Point2({name:"小张" , age:20, tall:180});
console.log(Point4.toValue())
console.log(Point4.getAge())
小张
20
prototype属性的constructor的属性指向类本身。 这点与es5相同
console.log(Point2.prototype.constructor === Point2)
true
类内部定义的方法是不可枚举的。
对枚举的说明
1。for - in 会遍历对象里可枚举的属性。包括自有属性和继承属性
2。可以通过Object.keys()会返回自有的可以枚举属性组成的数组
3。Object.getOwnPropertyNames()会返回自有的属性名。可枚举和不可枚举都会返回
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
Object.assign(Point2.prototype,{
toValue(){
return this.name
},
getAge(){
return this.age
}
})
console.log(Object.keys(Point2.prototype));
console.log(Object.getOwnPropertyNames(Point2.prototype))
[ 'toValue', 'getAge' ]
[ 'constructor', 'toSoring', 'toValue', 'getAge' ]
二。constructor
constructor方法是类的默认方法。 通过new实利对象时会自动调用这个方法。一个类必须包含constructor方法。 即使没有显示的添加也会有一个空的constructor被添加。constructor方法默认会返回实利对象(this),但是可以指定返回特定的对象
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
const Point4 = new Point2({name:"小张" , age:20, tall:180});
console.log(Point4)
class Class1 {
constructor() {
return {}
}
}
let a = new Class1();
console.log(a);
class Class2 {
constructor() {
return Object.create(null)
}
}
let b = new Class2();
console.log(b);
Point2 { name: '小张', age: 20, tall: 180 }
{}
[Object: null prototype] {}
三。类的实例
类必须通过new调用 ,否则会报错。 这也是和普通函数的区别。
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
const Point4 = Point2({name:"小张" , age:20, tall:180});
console.log(Point4)
TypeError: Class constructor Point2 cannot be invoked without 'new'
与es5一样实例的属性除非显示的定义在其类本身即this对象上。否则都会定义在原型上即class上
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
const Point4 = new Point2({name:"小张" , age:20, tall:180});
console.log(Point4.hasOwnProperty('name'));
console.log(Point4.hasOwnProperty("age"));
console.log(Point4.hasOwnProperty("toSoring"));
console.log(Point4.__proto__.hasOwnProperty("toSoring"))
true
true
false
true
与es5一样类的实例共享同一个原型对象。他们的原型对象都是Point2.prototype
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
const Point4 = new Point2({name:"小张" , age:20, tall:180});
const Point5 = new Point2({name:"小王", age:28, tall:173});
console.log(Point4.__proto__ === Point5.__proto__)
true
这就意味着可以通过__proto__为类添加新的方法。 值得注意的是这样做以后所以的实例对象都可以调用这个方法。并且__proto__并不是编程语言本身的特性。 故不推荐使用
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
}
const Point4 = new Point2({name:"小张" , age:20, tall:180});
Point4.__proto__.add = function () {
console.log("这是通过原型对象添加的方法")
};
Point4.add();
const Point5 = new Point2({name:"小王", age:28, tall:173});
Point5.add();
这是通过原型对象添加的方法
这是通过原型对象添加的方法
四, 取值函数(getter)和存值函数(setter)
与es5一样可以通过get函数读取属性和设置属性
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
toSoring(){
return `${this.name},${this.age},${this.tall}`
}
get prop(){
return this.name
}
set prop(value){
this.age = value
}
}
const Point4 = new Point2({name:"小张" , age:20, tall:180});
console.log(Point4.prop);
Point4.prop = 30;
console.log(Point4);
小张
Point2 { name: '小张', age: 30, tall: 180 }
五。 属性表达式。 类的属性可以使用表达式
let toSoring = 'toSoring';
class Point2 {
constructor({name,age,tall}) {
this.name = name;
this.age = age;
this.tall = tall
}
[toSoring](){
return `${this.name},${this.age},${this.tall}`
}
}
const Point4 = new Point2({name:"小张" , age:20, tall:180});
console.log(Point4.toSoring())
小张,20,180
六。类表达式 要注意的是类名只能在类的内部使用
let myClass = class Class {
constructor() {
this.age = 23
}
getData(){
return Class.name
}
};
let a = new myClass();
console.log(a.getData());
console.log(Class.name)
Class
ReferenceError: Class is not defined
类名在其内部没有使用到则可以简写
let myClass = class {};
利用类的表达式可以定义立即执行的类
let a = new class{
constructor() {
this.name = "小张"
}
};
console.log(a.name);
小张
七。静态方法
类的方法前面加上static关键字表示该方法为静态方法不会被继承。通过类直接调用。且静态方法中包含this时你在指向实例而是指向类本身
class Class {
constructor() {
this.age = 23
}
getData(){
return Class.name
}
static add(){
this.add1()
}
static add1(){
console.log("这是静态方法")
}
};
let a = new Class();
Class.add();
a.add()
这是静态方法
TypeError: a.add is not a function
父类的静态方法可以被子类继承
class Class {
constructor() {
this.age = 23
}
getData(){
return Class.name
}
static add(){
this.add1()
}
static add1(){
console.log("这是静态方法")
}
};
let a = new Class();
class Class1 extends Class {}
let b = new Class1();
Class1.add()
这是静态方法
八。实例属性的新写法
class number {
constructor() {
this.number = 0
}
geyNumber(){
return this.number
}
instNumber(){
this.number ++
}
}
class number1 {
number = 0;
geyNumber(){
return this.number
}
instNumber(){
this.number ++
}
}
九。静态属性
class B {}
B.name = "小张";
console.log(B.name);
let a = new B();
console.log(a.name);
B
undefined