谈谈 JS 中new的原理与实现

  • new 做了那些事?
  • new 返回不同的类型时会有什么表现?
  • 手写 new 的实现过程

new 关键词的主要作用就是执行一个构造函数、返回一个实例对象,在 new 的过程中,根据构造函数的情况,来确定是否可以接受参数的传递。下面我们通过一段代码来看一个简单的 new 的例子

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

这段代码比较容易理解,从输出结果可以看出,p 是一个通过 Person 这个构造函数生成的一个实例对象。

new  操作符可以帮助我们构建出一个实例,并且绑定上 this,内部执行步骤可大概分为以下几步:

  1. 创建一个新对象
  2. 对象连接到构造函数原型上,并绑定 this(this 指向新对象)
  3. 执行构造函数代码(为这个新对象添加属性)
  4. 返回新对象

在第四步返回新对象这边有一个情况会例外:

那么问题来了,如果不用 new 这个关键词,结合上面的代码改造一下,去掉 new,会发生什么样的变化呢?我们再来看下面这段代码

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

  • 从上面的代码中可以看到,我们没有使用 new 这个关键词,返回的结果就是 undefined。其中由于 JavaScript 代码在默认情况下 this 的指向是 window,那么 name 的输出结果就为 Jack,这是一种不存在 new 关键词的情况。
  • 那么当构造函数中有 return 一个对象的操作,结果又会是什么样子呢?我们再来看一段在上面的基础上改造过的代码。
function Person(){
   this.name = 'Jack'; 
   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 对象

但是这里要求构造函数必须是返回一个对象,如果返回的不是对象,那么还是会按照 new 的实现步骤,返回新生成的对象。接下来还是在上面这段代码的基础之上稍微改动一下

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的过程

function create(fn, ...args) {
  if(typeof fn !== 'function') {
    throw 'fn must be a function';
  }
	// 1、用new Object() 的方式新建了一个对象obj
  // var obj = new Object()
	// 2、给该对象的__proto__赋值为fn.prototype,即设置原型链
  // obj.__proto__ = fn.prototype

  // 1、2步骤合并
  // 创建一个空对象,且这个空对象继承构造函数的 prototype 属性
  // 即实现 obj.__proto__ === constructor.prototype
  var obj = Object.create(fn.prototype);

	// 3、执行fn,并将obj作为内部this。使用 apply,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
  var res = fn.apply(obj, args);
	// 4、如果fn有返回值,则将其作为new操作返回内容,否则返回obj
	return res instanceof Object ? res : obj;
};

  • 使用 Object.create 将 obj 的proto指向为构造函数的原型
  • 使用 apply 方法,将构造函数内的 this 指向为 obj
  • 在 create 返回时,使用三目运算符决定返回结果。

我们知道,构造函数如果有显式返回值,且返回值为对象类型,那么构造函数返回结果不再是目标实例

如下代码:

function Person(name) {
  this.name = name
  return {1: 1}
}
const person = new Person(Person, 'lucas')
console.log(person)
// {1: 1}

测试

//使用create代替new
function Person() {...}
// 使用内置函数new
var person = new Person(1,2)

// 使用手写的new,即create
var person = create(Person, 1,2)

new 被调用后大致做了哪几件事情

  • 让实例可以访问到私有属性;
  • 让实例可以访问构造函数原型(constructor.prototype)所在原型链上的属性;
  • 构造函数返回的最后结果是引用数据类型。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redux 是一种 JavaScript 状态管理库,它可以帮助我们管理应用程序的状态,并且可以在整个应用程序共享状态。Redux 的实现原理主要有以下几个方面: 1. Store:Redux 应用程序的所有状态都存储在一个单一的、不可变的存储区域,称为 "store"。store 是一个纯 JavaScript 对象,它包含了整个应用程序的状态。store 还包含了一些方法,用于获取状态、监听状态变化、更新状态等操作。 2. Action:Redux 应用程序的状态只能通过 "action" 来修改。action 是一个描述状态变化的普通 JavaScript 对象,它必须包含一个 "type" 属性,用于描述变化的类型。action 还可以包含一些其他的数据,用于描述变化的具体内容。 3. Reducer:Redux 应用程序的状态修改是通过 "reducer" 来实现的。reducer 是一个纯函数,它接受当前的状态和一个 action,然后返回一个新的状态。reducer 不能修改原来的状态,它只能返回一个全新的状态。Redux 应用程序可能会有多个 reducer,每个 reducer 负责管理一个部分状态。 4. Dispatch:Redux 应用程序的状态修改是通过 "dispatch" 来触发的。dispatch 是一个方法,它接受一个 action,然后将 action 发送给所有的 reducer。每个 reducer 都会接收到 action,然后根据 action 的类型来修改自己管理的状态。 5. Subscribe:Redux 应用程序的状态变化是通过 "subscribe" 来监听的。subscribe 是一个方法,它接受一个回调函数,每当状态发生变化时就会调用这个回调函数。我们可以在回调函数获取最新的状态,然后根据状态来更新应用程序的界面。 综上所述,Redux 的实现原理就是通过 store、action、reducer、dispatch 和 subscribe 这些机制来实现状态管理的。通过这些机制,我们可以将应用程序的状态集管理,从而带来更好的可维护性、可扩展性和可重用性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值