1. ES6中的继承
1.1 语法
// 父类
class Father{
}
// 子类继承父类
class Son extends Father {
}
1.2 示例
class Father {
constructor(name) {
this.name = name
}
say() {
console.log('我是' + this.name)
}
}
class Son extends Father {} // 子类继承父类的属性和方法
let son = new Son('刘德华')
son.say()
- 子类使用super关键字访问父类的方法
```javascript
//定义父类
class Father {
constructor(x, y) {
this.x = x
this.y = y
}
sum() {
} }console.log(this.x + this.y)
//子类继承父类 class Son extends Father { constructor(x, y) { super(x, y) //使用super调用了父类中的构造函数 } } let son = new Son(1, 2) son.sum() //结果为3
- **注意:**
- 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
- 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
- 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用 super 调用父类的构造函数
- super 必须在子类this之前调用
```javascript
// 父类有加法方法
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
// 子类继承父类加法方法 同时 扩展减法方法
class Son extends Father {
constructor(x, y) {
// 利用super 调用父类的构造函数 super 必须在子类this之前调用,放到this之后会报错
super(x, y)
this.x = x
this.y = y
}
subtract() {
console.log(this.x - this.y);
}
}
let son = new Son(5, 3)
son.subtract() //2
son.sum() //8
- 时刻注意this的指向问题,类里面的共有的属性和方法一定要加this使用
- constructor中的this指向的是new出来的实例对象
- 自定义的方法,一般也指向的new出来的实例对象
- 绑定事件之后this指向的就是触发事件的事件源
- 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象
2. ES6之前的继承
2.1 call()
- call()可以调用函数
- call()可以修改this的指向,使用call()的时候 参数一是修改后的this指向,参数2,参数3..使用逗号隔开连接
function fn(x, y) {
console.log(this)
console.log(x + y)
}
let o = {
name: 'andy'
}
fn.call(o, 1, 2) //调用了函数此时的this指向了对象o
2.2 子构造函数继承父构造函数中的属性
// 父构造函数
function Father(name, age) {
// this 指向父构造函数的对象实例
this.name = name
this.age = age
}
// 子构造函数
function Son(name, age, score) {
// this 指向子构造函数的对象实例
// 使用call方式实现子继承父的属性
Father.call(this, uname, age)
this.score = score
}
let son = new Son('刘德华', 18, 100)
console.log(son)
2.3 借用原型对象继承方法
// 父构造函数
function Father(uname, age) {
// this 指向父构造函数的对象实例
this.uname = uname
this.age = age
}
Father.prototype.money = function() {
console.log(100000)
}
// 子构造函数
function Son(uname, age, score) {
// this 指向子构造函数的对象实例
Father.call(this, uname, age)
this.score = score
}
// Son.prototype = Father.prototype 这样直接赋值会有问题
// 如果修改了子原型对象,父原型对象也会跟着一起变化
Son.prototype = new Father()
// 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
Son.prototype.constructor = Son
// 这个是子构造函数专门的方法
Son.prototype.exam = function() {
console.log('孩子要考试')
}
let son = new Son('刘德华', 18, 100);
console.log(son)
3. 拓展
call()的两个兄弟
apply()
- fun.apply(thisArg, [argsArray])
- thisArg: 在fun函数运行时指定的this值
- argsArray: 传递的值,必须包含在数组里面
- 返回值就是函数的返回值,因为他就是调用函数
// 需求:求数组的最大值 let arr = [4, 5, 1, 9] let max = Math.max.apply(null, arr) console.log(max)
bind()
- bind()方法不会调用函数,但是能改变函数内部this指向
- fun.bind(this.Arg, arg1, arg2, …)
- 返回由指定的this值和初始值参数改造的原函数拷贝
// 需求: 点击按钮,按钮禁用,经过三秒重新启用 const button = document.querySelector('button') button.onclick = function () { this.disabled = true setTimeout(function () { this.disabled = false }.bind(this), 3000) }
hasOwnProperty()
- 判断对象自身属性中是否具有指定的属性
let p = new Human('小明') p.hasOwnProperty('name') // true p.hasOwnProperty('speak') // false
- 判断对象自身属性中是否具有指定的属性
Object.assign()
- 将所有可枚举属性的值从一个或多个源对象复制到目标对象
- 它将返回目标对象 ```javascript const target = { a: 1, b: 2 } const source = { b: 4, c: 5 }
// 操作target对象 const returnedTarget = Object.assign(target, source) console.log(target) // { a: 1, b: 4, c: 5 } console.log(target === returnedTarget) // true
// 返回新的对象 const res = Object.assign({}, target, source)
- **Mixin**
- **通过不使用继承的方式让一个类中的方法被其他类复用**
```javascript
const mixin = (Base, mixins) => Object.assign(Base.prototype, mixins)
const Fly = {
canFly() {
console.log('I can fly')
}
}
class Mammal {
birthChild() {
console.log('I birth a baby')
}
}
mixin(Mammal, Fly)
let m = new Mammal()
m.birthChild()
m.canFly()