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()