class

304 阅读3分钟

Es5 中使用构造函数创建一个对象

  • ES5 使用构造函数创建一个对象
function Point(x, y) {
    // this 指向创建当前对象的实例
    this.x = x;
    this.y = y
}
  • 在Point对象的原型对象上创建的方法,当Point函数创建了实例之后,实例会继承这个方法,这就是为什么我们没有在Point构造函数上定义这个方法,但是我们却可以调用这个方法。实际上实例自身是没有这个方法的,但是会在创建的构造函数的原型上向上依次查找。
Point.prototype.getPoinstion = function () {
    return `(${this.x},${this.y})`
}
let p1 = new Point(2, 3)
console.log(p1)
// 当使用Point整个构造函数的时候,首先会创建一个空的对象,添加x,y属性,值就是你使用时传入的值,最后在构造函数中把实例返回,赋值给你定义的P1
console.log(p1.getPoinstion())

ES6 中的class ,每一个类的定义,一定要写constructor构造函数

class Points {
    /**
     * 
     * @return {返回this对象}
     * 也可以返回自己定义的对象,例如在constructor(){return {a: 'a'}},如果你自定义了返回对象,那么创建的类就不在是Point的实例对象了。
     * 可以使用 instanceof 检测 P2 instacneof Point,就会返回false
     */
    constructor(x, y) {
        this.x = x
        this.y = y
    }
    getPoinstion() {
        return `(${this.x},${this.y})`
    }
}
const p2 = new Points(4, 5)
console.log('es6 class create', p2)
console.info('fang fa ', p2.getPoinstion())
console.log(p2.hasOwnProperty('x'))
// getPoinstion是继承来的,定义在Point的原型对象上
console.log(p2.hasOwnProperty('getPoinstion')) // fasle
console.log(p2.__proto__.hasOwnProperty('getPoinstion')) // 所以在原型上可以找到此方法
let info = {
    _age: 18,
    set age(newValue) {
        console.log(newValue > 18 ? '我已经不再是小孩子了' : '啊,我还年轻')
    },
    get age() {
        console.log('我只是来获取值的')
        return this._age
    }
}
console.log(info.age)
info.age = 20
info.age = 16
class infos {
    constructor(name) {
        this._name = name
    }
    set name(newName) {
        console.log('new name is:', newName)
        this._name = newName
    }
    get name() {
        console.log('get name')
        return this._name
    }
    static getPersonName() {
        return infos.name
    }
}
const Info = new infos('王会')
Info.name = '小明'
console.log(Info.name)
  • 函数表达式
const func = function () {}
function funcs() {}
  • class 表达式
class Person {}
const child = class {}
console.log(new child())
// 实例方法,定义在类里边的方法,都可以被继承,都可以被实例调用的
// 如果不希望实例继承某个方法,将此方法标识为静态方法 static,只想让这个方法被类本身调用
// 类的静态方法,实例是无法继承的,所以实例无法调用。只能类自身去调用
// console.log(Info.getPersonName()) // console台会报错的
console.log(infos.getPersonName()) // 静态方法,使用类自身调用即可
  • class 添加属性还可以直接在实例下边添加,例如
  • 如果你想要这样写,一定要安装Babel,否则是会报错的(记住看babel的版本)。
class childs {
    age = 10 // 可以设置初始值、也可以不设置初始值、也可以把传递进来的值赋初始值
    constructor(x, y) {
        this.x = x
        this.y = y
    }
    getAge() {
        return this.age
    }
    getName() {
        return this.name
    }
}
console.log(new childs()) // 这样你可以看到三个属性
  • es6 明确规定类只有静态方法,没有静态属性
  • 给类添加静态属性
class Person2 {
    constructor() {
        this.x = 0
    }
    // static y = 5
}
Person2.y = 6
const p = new Person2()
  • es6是不提供私有方法的,只能通过变量名去模拟私有方法
class Teacher {
    func1() {}

    // 1. 从名字上区分,告诉你这个是想作为私有方法,让你不要用,但是用还是可以使用的。所以是假的。只是名字上的区分。
    // 但是这种命名是不安全的,在外边还是可以调用到这几个方法,所以这种你可以知道就是假的,不要这样写。
    _fun1() {
        return 'a'
    }
}
const T = new Teacher()
T._fun1()
  • 将私有方法移出模块
const _func2 = () => {}
class Teacher2 {
    func1() {
        _func2.call(this)
    }
}
const T2 = new Teacher2()
// T2._func2() // 这样就会直接报错不能使用了,因为已经是私有方法了。so 我注释了
  • 使用ES6的symbol
const func3 = Symbol('func3')
// 导出模块的方式
// export default class a {
//     static[func3]() {}
// }

// new.target 返回new 的构造函数
function P() {
    console.log(new.target)
}
const pp = new P()

class Doctor {
    constructor() {
        console.log(new.target)
    }
}
const DD = new Doctor()
  • 如果在子类中 new.target 会返回子类而不是父类
  • 一般用在创建一个类,这个类不能直接用来实例化,而是通过创建的子类来进行实例化
class Parent {
    constructor() {
        console.log(new.target)
        if(new.target === Parent) {
            throw Error('我是父类,不能实例化')
        }
    }
}
export class Child extends Parent {
    constructor() {
        super()
    }
}
// const c = new Parent() 就会抛出异常的
const c = new Child()