原有New的方法

  1. function Dog(name) {
  2. this.name = name;
  3. }
  4. Dog.prototype.bark = function () {
  5. console.log('wangwang');
  6. }
  7. Dog.prototype.sayName = function () {
  8. console.log('my name is ' + this.name);
  9. }
  10. let sanmao = new Dog('三毛');
  11. sanmao.sayName();
  12. sanmao.bark();

手撕New源码

首先也会把其当做普通函数执行

  • 1.浏览器会默认创建一个实例对象「对象 && 对象.proto===Dog.prototype」
  • 2.让方法执行的时候,方法中的this指向这个实例对象
  • 3.所以 构造函数体中出现的 this.xxx=xxx 都是给实例对象设置的私有属性和方法

  • 4.看函数的返回值,如果没有写或者返回的是原始值类型的值,则默认把实例对象返回;如果函数自己返回的是一个对象(含函数)则以自己返回的为主

// Ctor:constructor 需要创建实例的类
// params:数组中存储后期需要传递给Ctor的所有实参
// 方法目的:重写内置new,实现创造Ctor这个类的一个实例
function _new(Ctor, ...params) {//剩余运算符
    // 1.创建一个实例对象
    /* let obj = {};
    obj.__proto__ = Ctor.prototype; */
    let obj = Object.create(Ctor.prototype);

    // 2.把方法执行,让方法中的this指向这个实例对象  call改变函数中的this
    let result = Ctor.call(obj, ...params),//展开运算符
        type = typeof result;

    // 3.看方法执行的返回值:如果返回的是原始值或者没有写返回值,我们把创建的实例对象返回,如果函数自己返回个对象(含函数),则以自己返回的为主
    if (result !== null && (type === "object" || type === "function")) return result;
    return obj;
}
let sanmao = _new(Dog, '三毛');
sanmao.bark(); //=>"wangwang"
sanmao.sayName(); //=>"my name is 三毛"
console.log(sanmao instanceof Dog); //=>true
// Object.create(obj):创建一个空对象,并且把obj作为它的原型「空对象.__proto__===obj」
//   + obj必须是一个对象或者null
//   + Object.create(null)  创建一个空对象,但是没有__proto__

…运算符

  • 实参中的 ... 是展开运算符
  • 形参中的 ... 是剩余运算符