
JavaScript ES6实现继承
1 原型继承关系图
原型继承关系

创建对象的内存表现

2 class方式定义类
认识class定义类

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// ES5中定义类
// function Person() {}
// ES6定义类
// {key: value} -> 对象
// {表达式} -> 代码块
// {} -> 类的结构
class Person {
}
// 创建实例对象
var p1 = new Person()
var p2 = new Person()
console.log(p1, p2)
// 另外一种定义方法: 表达式写法(了解, 少用)
var Student = class {
}
var foo = function() {
}
var stu1 = new Student()
console.log(stu1)
</script>
</body>
</html>
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var obj = {
running: function() {},
eating: () => {},
swimming() {
}
}
// function Person() {
// }
// Person.prototype.running = function() {
// }
// 编程: 高内聚低耦合
class Person {
// 1.类中的构造函数
// 当我们通过new关键字调用一个Person类时, 默认调用class中的constructor方法
constructor(name, age) {
this.name = name
this.age = age
}
// 2.实例方法
// 本质上是放在Person.prototype
running() {
console.log(this.name + " running~")
}
eating() {
console.log(this.name + " eating~")
}
}
// 创建实例对象
var p1 = new Person("why", 18)
// 使用实例对象中属性和方法
console.log(p1.name, p1.age)
p1.running()
p1.eating()
// 研究内容
console.log(Person.prototype === p1.__proto__)
console.log(Person.running)
console.log(Person.prototype.running)
</script>
</body>
</html>
类和构造函数的异同

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// function定义类
function Person1(name, age) {
this.name = name
this.age = age
}
Person1.prototype.running = function() {}
Person1.prototype.eating = function() {}
var p1 = new Person1("why", 18)
console.log(p1.__proto__ === Person1.prototype)
console.log(Person1.prototype.constructor)
console.log(typeof Person1) // function
// 不同点: 作为普通函数去调用
Person1("abc", 100)
// class定义类
class Person2 {
constructor(name, age) {
this.name = name
this.age = age
}
running() {}
eating() {}
}
var p2 = new Person2("kobe", 30)
console.log(p2.__proto__ === Person2.prototype)
console.log(Person2.prototype.constructor)
console.log(typeof Person2)
// 不同点: class定义的类, 不能作为一个普通的函数进行调用
Person2("cba", 0)
</script>
</body>
</html>
类的构造函数

类的实例方法

类的访问器方法

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 针对对象
// 方式一: 描述符
// var obj = {
// _name: "why"
// }
// Object.defineProperty(obj, "name", {
// configurable: true,
// enumerable: true,
// set: function() {
// },
// get: function() {
// }
// })
// 方式二: 直接在对象定义访问器
// 监听_name什么时候被访问, 什么设置新的值
var obj = {
_name: "why",
// setter方法
set name(value) {
this._name = value
},
// getter方法
get name() {
return this._name
}
}
obj.name = "kobe"
console.log(obj.name)
</script>
</body>
</html>
类的静态方法

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// function Person() {}
// // 实例方法
// Person.prototype.running = function() {}
// // 类方法
// Person.randomPerson = function() {}
// var p1 = new Person()
// p1.running()
// Person.randomPerson()
// class定义的类
var names = ["abc", "cba", "nba", "mba"]
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
// 实例方法
running() {
console.log(this.name + " running~")
}
eating() {}
// 类方法(静态方法)
static randomPerson() {
console.log(this)
var randomName = names[Math.floor(Math.random() * names.length)]
return new this(randomName, Math.floor(Math.random() * 100))
}
}
var p1 = new Person()
p1.running()
p1.eating()
var randomPerson = Person.randomPerson()
console.log(randomPerson)
</script>
</body>
</html>
3 extends实现继承
ES6类的继承 - extends

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 定义父类
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
running() {
console.log("running~")
}
eating() {
console.log("eating~")
}
}
class Student extends Person {
constructor(name, age, sno, score) {
// this.name = name
// this.age = age
super(name, age)
this.sno = sno
this.score = score
}
// running() {
// console.log("running~")
// }
// eating() {
// console.log("eating~")
// }
studying() {
console.log("studying~")
}
}
var stu1 = new Student("why", 18, 111, 100)
stu1.running()
stu1.eating()
stu1.studying()
class Teacher extends Person {
constructor(name, age, title) {
// this.name = name
// this.age = age
super(name, age)
this.title = title
}
// running() {
// console.log("running~")
// }
// eating() {
// console.log("eating~")
// }
teaching() {
console.log("teaching~")
}
}
</script>
</body>
</html>
super关键字

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class Animal {
running() {
console.log("running")
}
eating() {
console.log("eating")
}
static sleep() {
console.log("static animal sleep")
}
}
class Dog extends Animal {
// 子类如果对于父类的方法实现不满足(继承过来的方法)
// 重新实现称之为重写(父类方法的重写)
running() {
console.log("dog四条腿")
// 调用父类的方法
super.running()
// console.log("running~")
// console.log("dog四条腿running~")
}
static sleep() {
console.log("趴着")
super.sleep()
}
}
var dog = new Dog()
dog.running()
dog.eating()
Dog.sleep()
</script>
</body>
</html>
继承内置类

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.创建一个新的类, 继承自Array进行扩展
class HYArray extends Array {
get lastItem() {
return this[this.length - 1]
}
get firstItem() {
return this[0]
}
}
var arr = new HYArray(10, 20, 30)
console.log(arr)
console.log(arr.length)
console.log(arr[0])
console.log(arr.lastItem)
console.log(arr.firstItem)
// 2.直接对Array进行扩展
Array.prototype.lastItem = function() {
return this[this.length - 1]
}
var arr = new Array(10, 20, 30)
console.log(arr.__proto__ === Array.prototype)
console.log(arr.lastItem())
// 函数apply/call/bind方法 -> Function.prototype
</script>
</body>
</html>
类的混入mixin

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// JavaScript只支持单继承(不支持多继承)
function mixinAnimal(BaseClass) {
return class extends BaseClass {
running() {
console.log("running~")
}
}
}
function mixinRunner(BaseClass) {
return class extends BaseClass {
flying() {
console.log("flying~")
}
}
}
class Bird {
eating() {
console.log("eating~")
}
}
// var NewBird = mixinRunner(mixinAnimal(Bird))
class NewBird extends mixinRunner(mixinAnimal(Bird)) {
}
var bird = new NewBird()
bird.flying()
bird.running()
bird.eating()
</script>
</body>
</html>
在react中的高阶组件

4 Babel的ES6转ES5
babel可以将ES6转成ES5代码

5 面向对象多态理解
JavaScript中的多态

Java面向对象的多态理解
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 继承是多态的前提
// shape形状
class Shape {
getArea() {}
}
class Rectangle extends Shape {
constructor(width, height) {
super()
this.width = width
this.height = height
}
getArea() {
return this.width * this.height
}
}
class Circle extends Shape {
constructor(radius) {
super()
this.radius = radius
}
getArea() {
return this.radius * this.radius * 3.14
}
}
var rect1 = new Rectangle(100, 200)
var rect2 = new Rectangle(20, 30)
var c1 = new Circle(10)
var c2 = new Circle(15)
// 表现形式就是多态
/*
在严格意义的面向对象语言中, 多态的是存在如下条件的:
1.必须有继承(实现接口)
2.必须有父类引用指向子类对象
*/
function getShapeArea(shape) {
console.log(shape.getArea())
}
getShapeArea(rect1)
getShapeArea(c1)
var obj = {
getArea: function() {
return 10000
}
}
getShapeArea(obj)
getShapeArea(123)
</script>
</body>
</html>
JS面向对象的多态理解
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 多态的表现: JS到处都是多态
function sum(a1, a2) {
return a1 + a2
}
sum(20, 30)
sum("abc", "cba")
// 多态的表现
var foo = 123
foo = "Hello World"
console.log(foo.split())
foo = {
running: function() {}
}
foo.running()
foo = []
console.log(foo.length)
</script>
</body>
</html>
6 ES6对象的增强
字面量的增强

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
/*
1.属性的增强
2.方法的增强
3.计算属性名的写法
*/
var name = "why"
var age = 18
var key = "address" + " city"
var obj = {
// 1.属性的增强
name,
age,
// 2.方法的增强
running: function() {
console.log(this)
},
swimming() {
console.log(this)
},
eating: () => {
console.log(this)
},
// 3.计算属性名
[key]: "广州"
}
obj.running()
obj.swimming()
obj.eating()
function foo() {
var message = "Hello World"
var info = "my name is why"
return { message, info }
}
var result = foo()
console.log(result.message, result.info)
</script>
</body>
</html>
解构Destructuring

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var names = ["abc", "cba", undefined, "nba", "mba"]
// 1.数组的解构
// var name1 = names[0]
// var name2 = names[1]
// var name3 = names[2]
// 1.1. 基本使用
// var [name1, name2, name3] = names
// console.log(name1, name2, name3)
// 1.2. 顺序问题: 严格的顺序
// var [name1, , name3] = names
// console.log(name1, name3)
// 1.3. 解构出数组
// var [name1, name2, ...newNames] = names
// console.log(name1, name2, newNames)
// 1.4. 解构的默认值
var [name1, name2, name3 = "default"] = names
console.log(name1, name2, name3)
// 2.对象的解构
var obj = { name: "why", age: 18, height: 1.88 }
// var name = obj.name
// var age = obj.age
// var height = obj.height
// 2.1. 基本使用
// var { name, age, height } = obj
// console.log(name, age, height)
// 2.2. 顺序问题: 对象的解构是没有顺序, 根据key解构
// var { height, name, age } = obj
// console.log(name, age, height)
// 2.3. 对变量进行重命名
// var { height: wHeight, name: wName, age: wAge } = obj
// console.log(wName, wAge, wHeight)
// 2.4. 默认值
var {
height: wHeight,
name: wName,
age: wAge,
address: wAddress = "中国"
} = obj
console.log(wName, wAge, wHeight, wAddress)
// 2.5. 对象的剩余内容
var {
name,
age,
...newObj
} = obj
console.log(newObj)
// 应用: 在函数中(其他类似的地方)
function getPosition({ x, y }) {
console.log(x, y)
}
getPosition({ x: 10, y: 20 })
getPosition({ x: 25, y: 35 })
function foo(num) {}
foo(123)
</script>
</body>
</html>
解构的应用场景
