6.(ECMAScript)es6完全解读(5)

1. 重点提炼

  • 面向过程
  • 面向对象
  • es5/es6中的类与继承等基本使用

2. 面向过程与面向对象

面向过程 => 分析需求整个过程由哪个几个步骤组成,逐步实现。

面向对象 => 分析需求中由哪几个对象组成,分析每种对象应该由哪些属性和方法 / 行为组成。

如下:

隐藏对象 => 可能是人、手、或者其他工具将大象放入冰箱

image-20201122203407675

JavaScript是一种基于对象(object-based)的语言

对于面向对象编程而言,更关注类的声明、属性、方法、静态方法、继承、多态、私有属性。

Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象。但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类)。


2.1 类与对象

狗这个范围比较大,很抽象 => 代表类

我家的狗,很具体到实体 => 对象

类(class)是对象(object)的模版,定义了同一组对象共有的属性和方法。


3. ES5中的类与继承

一般定义函数首字母 小写,约定俗成首字母定为大写

类与构造函数 =>

// 构造函数
function People(name, age) {
    console.log(this)
    // 实例属性
    this.name = name
    this.age = age
}

// 实例化对象
let p1 = new People('张三', 24) 
console.log(p1)

let p2 = new People('李四', 20)
console.log(p2)

image-20201122213008892

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.02
Branch: branch02

commit description:a2.02(ES5中的类与继承——类与构造函数 )

tag:a2.02


类的方法 =>

// 类
// 构造函数
function People(name, age) {
    console.log(this)
    // 实例属性
    this.name = name
    this.age = age
    // 方法
    this.showName = function () {
        console.log('我的名字是' + this.name)
    }
}

// 实例化对象
let p1 = new People('张三', 24)
console.log(p1)
p1.showName()

let p2 = new People('李四', 20)
console.log(p2)
p2.showName()

image-20201122213323186

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.03
Branch: branch02

commit description:a2.03(ES5中的类与继承——类的方法 )

tag:a2.03


但是一般情况下,不会把方法定义在构造函数中,因为每次new一个对象,就会new出一个方法,这样都放在对象下并不好,很累赘。实际应该放在类的原型下 =>

// 类
// 构造函数
function People(name, age) {
    console.log(this)
    // 实例属性
    this.name = name
    this.age = age
}

// 实例方法
People.prototype.showName = function () {
    console.log('我的名字是' + this.name)
}

// 实例化对象
let p1 = new People('张三', 24)
console.log(p1)
p1.showName()

let p2 = new People('李四', 20)
console.log(p2)
p2.showName()

如此就不会每次new一个实例,再new方法,避免都是一个东西,却占了很多内存。原型实际是一个类共有的,每个实例无需再多开辟的内存。它属于这个类所有实例共享的公共空间

image-20201122213723432

image-20201122213754359

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.04
Branch: branch02

commit description:a2.04(ES5中的类与继承——原型方法)

tag:a2.04


静态方法 =>

使用Math.max时,并没有先new,而是直接调用了。

// 静态方法
console.log(Math.max(4, 5))
console.log(Math.random())

image-20201122215617726

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.05
Branch: branch02

commit description:a2.05(ES5中的类与继承——静态方法)

tag:a2.05


静态属性、方法 是定义在类下的,而实例属性定义在构造函数中

构造函数中的this指向实例化对象,静态方法中this指向当前构造函数,而非实例化对象,因此没有age属性。

// 类
// 构造函数
function People(name, age) {
    console.log(this)
    // 实例属性
    this.name = name
    this.age = age
    // 静态属性
    People.count++
}

// 静态属性
People.count = 0
// 静态方法
People.getCount = function(){
    console.log(this)
    console.log(this.age) // undefined
    console.log('当前共有' + People.count + '个人')
}

// 实例方法
People.prototype.showName = function () {
    console.log('我的名字是' + this.name)
}

// 实例化对象
let p1 = new People('张三', 24)
console.log(p1)
p1.showName()

let p2 = new People('李四', 20)
console.log(p2)
p2.showName()

// 查看实例化次数
console.log(People.count)
People.getCount()

image-20201122231817717

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.06
Branch: branch02

commit description:a2.06(ES5中的类与继承——静态属性、方法特点)

tag:a2.06


ES5继承 =>

父类.call(this, 父类属性对应参数) => 构造函数继承

也可

Dog.prototype = deepCopy(Animal.prototype); 。注意这里必须进行深拷贝才行。

// 父类
function Animal(name) {
    this.name = name
}
Animal.prototype.showName = function () {
    console.log('名字是:' + this.name)
}

// 组合继承 => 属性 + 方法
// 子类
function Dog(name, color) {
    Animal.call(this, name) // 继承属性
    this.color = color
}
// 继承方法(原型继承)
Dog.prototype = new Animal()
Dog.prototype.constuctor = Dog

let d1 = new Dog('wangcai', 'white')
console.log(d1)
d1.showName()

image-20201123000526413

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.07
Branch: branch02

commit description:a2.07(ES5中的类与继承——ES5继承)

tag:a2.07


4. ES6中的类与继承

es6 提供了关键字class => 声明类

class的方式是 function方式的语法糖。

虽然 ES6在类的定义上仅是 ES5定义类的语法糖,但是从开发者的角度而言,开发更有效率了,代码可阅读性大大提升。

关键字construct => 构造函数

方法直接定义在类中即可 =>

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    showName() {
        console.log(this.name)
    }
}
let p1 = new People('zhangsan', 30)
console.log(p1)

image-20201123003050138

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.08
Branch: branch02

commit description:a2.08(ES6中的类与继承——ES6类基本使用)

tag:a2.08


综上class关键字实际就是语法糖,实际还是function

es6实现继承 => extends关键字

继承父类属性 => super

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    showName() {
        console.log(this.name)
    }
}
let p1 = new People('zhangsan', 30)
console.log(p1)

class Coder extends People {
    constructor(name, age, company) {
        super(name, age)
        this.company = company
    }
    showCompany() {
        console.log(this.company)
    }
}

let c1 = new Coder('lisi', 25, 'Tecent')
console.log(c1)
c1.showName()
c1.showCompany()

image-20201123100133155

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.09
Branch: branch02

commit description:a2.09(ES6中的类与继承——ES6类继承)

tag:a2.09


之前的实例属性都是定义在construct里的,实际在es6中可把属性定义在类的最顶层,即在大括号里的第一层,而以上是construct在大括号里的第二层了。

es6中可把属性定义在类的最顶层 => 通过getset关键字,相当于javac#setget

注意:set函数不可以写成如下形式,会掉入死循环,不停地压栈,致使栈内存奔溃。

    set sex(val) { 
        this.sex = val
    }

应该直接return

实际一般都会在构造函数中设定set对应属性的初始值,通过_sex临时属性,set的时候就可以直接this._sex = valget的时候也获取它的值即可。

并且取值、赋值时,setget相当于属性拦截,可引入业务逻辑操作 =>

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
        this._sex = -1
    }
    get sex() { // 属性
        if (this._sex === 1) {
            return 'male'
        } else if (this._sex === 0) {
            return 'female'
        } else {
            return 'error'
        }
    }
    set sex(val) { // 1:male 0:female
        if (val === 0 || val === 1) {
            this._sex = val
        }
    }
    showName() {
        console.log(this.name)
    }
}
let p1 = new People('zhangsan', 30)
console.log(p1)
p1.sex = 5
console.log(p1.sex)

class Coder extends People {
    constructor(name, age, company) {
        super(name, age)
        this.company = company
    }
    showCompany() {
        console.log(this.company)
    }
}

let c1 = new Coder('lisi', 25, 'Tecent')
console.log(c1)
c1.showName()
c1.showCompany()
c1.sex = 1
console.log(c1.sex)

image-20201123103259791

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.10
Branch: branch02

commit description:a2.10(ES6中的类与继承——ES6类中的set与get)

tag:a2.10


静态方法 和 属性

静态 => 关键字static

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
        this._sex = -1
    }
    get sex() { // 属性
        if (this._sex === 1) {
            return 'male'
        } else if (this._sex === 0) {
            return 'female'
        } else {
            return 'error'
        }
    }
    set sex(val) { // 1:male 0:female
        if (val === 0 || val === 1) {
            this._sex = val
        }
    }
    showName() {
        console.log(this.name)
    }
    // 静态方法
    static getCount() {
        return 5
    }
}
let p1 = new People('zhangsan', 30)
console.log(p1)
p1.sex = 5
console.log(p1.sex)
console.log(People.getCount())

class Coder extends People {
    constructor(name, age, company) {
        super(name, age)
        this.company = company
    }
    showCompany() {
        console.log(this.company)
    }
}

let c1 = new Coder('lisi', 25, 'Tecent')
console.log(c1)
c1.showName()
c1.showCompany()
c1.sex = 1
console.log(c1.sex)
console.log(Coder.getCount())

子级也可以调用的到父级的静态方法。

image-20201123103621528

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.11
Branch: branch02

commit description:a2.11(ES6中的类与继承——ES6类中的静态方法)

tag:a2.11


静态属性 => es6明确规定在class内部只能定义静态方法,没有静态属性

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
        this._sex = -1
    }
    static count = 0
    get sex() { // 属性
        if (this._sex === 1) {
            return 'male'
        } else if (this._sex === 0) {
            return 'female'
        } else {
            return 'error'
        }
    }
    set sex(val) { // 1:male 0:female
        if (val === 0 || val === 1) {
            this._sex = val
        }
    }
    showName() {
        console.log(this.name)
    }
    // 静态方法
    static getCount() {
        return 5
    }
}

不支持在类内定义静态属性。

image-20201123104035422

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.12
Branch: branch02

commit description:a2.12(ES6中的类与继承——不支持在类内定义静态属性)

tag:a2.12


静态属性实际和es5一样,直接通过类名在类外定义即可。

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
        this._sex = -1
    }
    get sex() { // 属性
        if (this._sex === 1) {
            return 'male'
        } else if (this._sex === 0) {
            return 'female'
        } else {
            return 'error'
        }
    }
    set sex(val) { // 1:male 0:female
        if (val === 0 || val === 1) {
            this._sex = val
        }
    }
    showName() {
        console.log(this.name)
    }
    // 静态方法
    static getCount() {
        return 5
    }
}

// 静态属性
People.count = 9
console.log(People.count)
console.log(typeof People) // function

let p1 = new People('zhangsan', 30)
console.log(p1)
p1.sex = 5
console.log(p1.sex)
console.log(People.getCount())

class Coder extends People {
    constructor(name, age, company) {
        super(name, age)
        this.company = company
    }
    showCompany() {
        console.log(this.company)
    }
}

console.log(Coder.count)

let c1 = new Coder('lisi', 25, 'Tecent')
console.log(c1)
c1.showName()
c1.showCompany()
c1.sex = 1
console.log(c1.sex)
console.log(Coder.getCount())

可以看到虽然有了关键字class,但还是基于function原型的语法糖,底层还是es5

image-20201123104657916

参考:https://github.com/6xiaoDi/blog-ECMScript-Series/tree/a2.13
Branch: branch02

commit description:a2.13(ES6中的类与继承——静态属性)

tag:a2.13


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值