redux的isPlainObject源码

isPlainObject函数是redux自己用来判断传递给reduceraction对象是一个plain object,也就是通过字面量方式或者Object构造函数的方式生成的对象,中间没有发生其他的继承情况,保持action对象是一个plain object的作用是,方便reducer进行处理,不用处理其他的情况(例如:promise/function/class实例等等),另一方面,也是方便的对状态进行记录或者回溯(比如说redux devtool工具里的action删除、跳过等操作)

/**
 * @param {any} obj The object to inspect.
 * @returns {boolean} True if the argument appears to be a plain object.
 */
export default function isPlainObject(obj) {
  if (typeof obj !== 'object' || obj === null) return false

  let proto = obj
  while (Object.getPrototypeOf(proto) !== null) {
    proto = Object.getPrototypeOf(proto)
  }

  return Object.getPrototypeOf(obj) === proto
}

代码理解也不难,就是通过一个while循环拿到参数对象原型链的最后一个值,普通的对象while循环结束后proto的值是:Object.prototype,通过Object.create(null)生成的对象proto的值是:null

但是为什么不直接进行下面的判断呢?

return Object.getPrototypeOf(obj) === Object.prototype || Object.getPrototypeOf(obj) === null

这段代码仿佛和reduxcode的作用是一样的,我最开始也是不太理解,查看了官方github仓库下面的讨论后才了解到原因~~

redux的代码是为了防止一些边界情况的出现,对于一些cross-realm情况(例如跨frame访问变量时),使用我的代码就可能出现问题,比如说在一个frame里面调用父窗口的函数:

window.parent.someFunction(["hello", "world"])

在父窗口中有someFunction的定义:

function someFunction(arg) {
  if (arg instanceof Array) {
    // ... operate on the array
  }
}

这样调用并不会执行if语句的代码,因为两段代码所处的javascript执行环境是不一样的,每个frame都有自己的执行环境,他们也不会共享原型链,也就是说两个执行环境中的Array Object构造函数都是不等的,那么if语句的判断就为false,这个数组并不是继承的父窗口执行环境里的Array

这种情况下使用我的代码进行plain object判断自然也会出现问题。像其他的一些情况,例如不同的window窗口都算是处于不同的javascript执行环境~~


发现错误请留言告诉我~~~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值