new关键字

new 关键词的主要作用就是执行一个构造函数、返回一个实例对象。在 new 的过程中,根据构造函数的情况,来确定是否可以接受参数的传递。

function Person(){
   this.name = 'Jack';
}
var p = new Person(); 
console.log(p.name)  // Jack

这段代码做了四件事

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(this 指向新对象);
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象。
function Person(){
   this.name = 'Tom'; 
   return {age: 18}
}
var p = new Person(); 
console.log(p)  // {age: 18}
console.log(p.name) // undefined
console.log(p.age) // 18

构造函数最后 return 出来的是一个和 this 无关的对象时,new 命令会直接返回这个新对象,而不是通过 new 执行步骤生成的 this 对象。

function Person(){
   this.name = 'Jack'; 
   return 'tom';
}
var p = new Person(); 
console.log(p)  // {name: 'Jack'}
console.log(p.name) // Jack

当构造函数中 return 的不是一个对象时,那么它还是会根据 new 关键词的执行逻辑,生成一个新的对象(绑定了最新 this),最后返回出来

因此new 关键词执行之后总是会返回一个对象,要么是实例对象,要么是 return 语句指定的对象。
new的实现
new被访问后做的几件事情

  • 让实例可以访问私有属性
  • 让实例可以访问构造函数原型(constructor.prototype)所在原型链上的属性
  • 构造函数返回的是引用数据类型
 function _new(contor, ...args) {
     if (typeof contor !== "function") {
         throw "contro must be a function"
     }
     // 构造一个obj实例对象
     let obj = new Object()
     // __proto__可以理解为“构造器的原型”,即__proto__===constructor.prototype
     obj.__proto__ = Object.create(contor.prototype)
     let res = contor.apply(obj, [...args])

     let isObj = typeof res === "object" && res !== null;
     let isFunction = typeof res === "function"
     return isObj || isFunction ? res : obj
 }

apply,call, bind

这三个函数比较常见,改变this指向

func.call(thisArg, param1, param2, ...)
func.apply(thisArg, [param1,param2,...])
func.bind(thisArg, param1, param2, ...)

call,apply实现

 Function.prototype.call = function(context,...args){
     var context = context || window;
     context.fn = this;
     // 立即执行
     let result = eval("context.fn(...args)")
     delete context.fn
     return result;
 }

 Function.prototype.apply = function(context,args){
    var context = context || window;
    context.fn = this;
    // 立即执行
    let result = eval("context.fn(...args)")
    delete context.fn
    return result;
}
 Function.prototype.bind = function (context, ...args) {
     if (typeof this !== "function") {
         throw new Error("this must be a function")
     }
     let self = this;
     let fbound = function () {
         self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)))
     }

     if (this.prototype) {
         // 返回的过程中原型链对象上的属性不能丢失,将 this.prototype 上面的属性挂到 fbound 的原型上面
         fbound.prototype = Object.create(this.prototype)
     }
     // 实现 bind 的核心在于要返回一个函数
     return fbound
 }

HeiYanjing
45 声望1 粉丝

生活本就很艰难,且行且珍惜。