美文网首页
Call, apply 和 bind

Call, apply 和 bind

作者: _不能说的秘密i | 来源:发表于2019-11-17 20:34 被阅读0次

Call, apply 和 bind

  • 作用: 改变调用函数的 this 指向
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']

原型链继承

  1. 修改子类的原形对象为父类的实例对象
  2. 修改子类原型对象的构造函数为自身的构造函数(此时的构造函数已被改变为父类)
// 人类
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); 

相关文章

网友评论

      本文标题:Call, apply 和 bind

      本文链接:https://www.haomeiwen.com/subject/ejlmictx.html