Call, apply 和 bind
let obj1 = {
name: "obj1 name",
showName() {
console.log(this.name);
},
showMsg(...args) {
console.log(this.name);
console.log(args);
}
};
let obj2 = {
name: "obj2 name"
};
// -- call --
obj1.showName(); // obj1 name
obj1.showName.call(obj2); // obj2 name
// -- apply --
obj1.showMsg.apply(obj2, ['111', '222']); // obj2 ['111', '222']
原型链继承
- 修改子类的原形对象为父类的实例对象
- 修改子类原型对象的构造函数为自身的构造函数(此时的构造函数已被改变为父类)
// 人类
function Person() {
this.age = 10;
this.friends = ['jack', 'tom', 'jerry'];
this.run = function () {
console.log("--- run ---");
}
}
Person.prototype.say = function () {
console.log("--- say ---");
}
// 学生类
// 1. 将 Student 的原形修改为 Person 类的实例对象
// 2. 将 Student 的原形构造函数再修复会 Student 对象
Student.prototype = new Person();
Student.prototype.constructor = Student;
function Student() {
this.name = 'jason';
}
const stu = new Student();
stu.say(); // --- run ---
stu.run(); // --- say ---
console.log(stu.age); // 10
console.log(stu.name); // jason
组合式继承:
- 原型链继承的问题: 如果是对象的属性是复杂数据类型会被多个子类实例共享
//- 问题
const stu1 = new Student();
const stu2 = new Student();
stu1.friends = [];
// 此时两个对象的 friends 属性都被同时改变了
console.log(stu1.friends); // []
console.log(stu2.friends); // []
// 人类
function Person() {
this.age = 10;
this.friends = ['jack', 'tom', 'jerry'];
this.run = function () {
console.log("--- run ---");
}
}
Person.prototype.say = function () {
console.log("--- say ---");
}
// 学生类
Student.prototype = new Person();
Student.prototype.constructor = Student;
function Student() {
Person.call(this);
this.name = 'jason';
}
const stu1 = new Student();
const stu2 = new Student();
stu1.friends = [];
console.log(stu1.friends); // []
console.log(stu2.friends); // [ 'jack', 'tom', 'jerry' ]
寄生式继承
- 组合继承的问题: 调用两次父类构造函数, 但是这些属性是重复的, 实例对象上有一份, 原型上还有一份
- 需要一个中间构造函数
// 父类
function Person(age, friends) {
this.age = age;
this.friends = friends;
}
// 中间临时构造函数
function Temp() { }
Temp.prototype = Person.prototype;
const StudentPrototype = new Temp();
// 子类
Student.prototype = StudentPrototype;
StudentPrototype.constructor = Student;
function Student(options) {
const { name, age, friends } = options;
Person.call(this, age, friends);
this.name = name;
}
// 使用
let stu1 = new Student({
name: 'alex',
age: 10,
friends: ['tom']
});
let stu2 = new Student({
name: 'jason',
age: 10,
friends: ['jerry']
});
console.log(stu1);
console.log(stu2);
多层继承
// 动物类
function Animal(name, age) {
this.name = name;
this.age = age;
}
Animal.prototype.eat = function() {
console.log('吃');
}
Animal.prototype.run = function () {
console.log('跑');
}
// 人类
function Person (job, name, age) {
Animal.call(this, name, age);
this.job = job;
}
// 寄生式继承
function Temp() {}
Temp.prototype = Animal.prototype;
Person.prototype = new Temp;
Person.prototype.constructor = Person;
Person.prototype.jump = function() {
console.log('跳');
}
// 寄生式继承
function Temp2 () {}
Temp.prototype = Person.prototype;
Student.prototype = new Temp2();
Student.prototype.constructor = Student;
function Student(options) {
const {name, age, job, className} = options;
Person.call(this, name, age, job);
this.className = className;
}
Student.prototype.study = function () {
console.log('学习');
}
const stu1 = new Student({ name: 'tom', age : 10, job: 'student', className: 'dev' });
const stu2 = new Student({ name: 'jerry', age : 20, job: 'teacher', className: 'test' });
console.log(stu1);
console.log(stu2);
网友评论