通过call和new 的原理来理解经典继承

call原理

call可以改变一个函数的作用域

let a = {
  name: 'foo',
  fn: function() {
    console.log(this.name);
  }
};

let b = {
  name: 'bar'
};
a.fn.call(b); // 输出 bar
实现一个自己的call
// 在函数的原型上定义自己的call
Function.prototype.mycall = function(context) {
  // context 新作用域  =>  b
  // this 指向要调用的方法   => a.fn
  if(typeof this !== 'function'){
    throw new TypeError('不是方法!');
  }
  // 获取参数
  let args = [...arguments].slice(1);
  // 将要调用的方法添加到新作用域
  context.fn = this;
  // 在新作用域执行方法
  let result = context.fn(...args);
  delete context.fn;
  // 要调用的方法如果没有返回  result = undefined
  return result;
}

从代码中可以看出,call实际就是将要调用的方法添加到新作用域,并执行。

new原理

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。

new用来创建对象

function Person(name, age) {
  this.name = name;
  this.age = age;
  console.log(this);
}

Person('xm',12);  // this指向window
let me = new Person('xg',18);  // this指向me
console.log(me.age);  // 输出18
  • 当使用new关键字时,Person是构造函数
  • 不使用new关键字时,Person就是普通函数
实现一个自己的new
function myNew (fun) {
  // 假设myNew返回的函数叫  newReturn
  return function () {
    // 创建一个新对象且将其隐式原型指向构造函数原型
    let obj = {
      __proto__ : fun.prototype
    };
    // 执行构造函数
    // 根据前面的call原理,构造函数的this指向obj
    // 执行完构造函数,obj拥有name,age属性
    fun.call(obj, ...arguments);
    // 返回该对象
    return obj;
  }
}
let she = myNew(Person)('xh', 16) // {name: "xh", age: 16}
// myNew(Person) = newReturn
// myNew(Person)('xh', 16) = newReturn('xh', 16)

经典继承

function Rectangle(length,width) {
  this.length = length;
  this.width = width;
}
Rectangle.prototype.getSize = function() {
  return this.length * this.width;
}

function Square(edgeLength) {
  // 调用Rectangle构造函数
  // Square实例拥有了Rectangle的属性
  Rectangle.call(this,edgeLength,edgeLength);
  this.getSize = function() {
    return this.length * this.width;
  }
}
// 创建一个空对象 obj
// 将 obj.__proto__ = Rectangle.prototype
// obj 作为新的上下文执行构造函数
// 返回obj————新的实例
let rect = new Rectangle(3,4);
console.log(rect.getSize());
let square = new Square(5);
console.log(square.getSize());

经典继承也有自身的缺点

  • 方法都在构造函数中定义
  • 因为方法都在构造函数中定义,所以每次创建实例都会重新赋值一遍方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值