Lodash源码阅读-baseAssignValue

Lodash 源码阅读-baseAssignValue

功能概述

baseAssignValue 是 Lodash 中的一个内部工具函数,用于将值赋给对象的属性,是 assignValue 的基础实现版本。它的特点是直接赋值,不进行任何相等性检查,同时对 __proto__ 属性有特殊处理,以防止原型污染攻击。

前置学习

依赖函数

  • defineProperty :对象属性定义工具,用于安全地处理 __proto__ 属性

技术知识

  • 对象属性赋值:JavaScript 中对象属性的赋值机制
  • 原型污染攻击 :通过修改 __proto__ 属性导致的安全问题
  • Object.defineProperty:JavaScript 中定义或修改对象属性的 API

源码实现

javascript 复制代码
function baseAssignValue(object, key, value) {
  if (key == "__proto__" && defineProperty) {
    defineProperty(object, key, {
      configurable: true,
      enumerable: true,
      value: value,
      writable: true,
    });
  } else {
    object[key] = value;
  }
}

实现思路

baseAssignValue 的实现思路非常直接:

  1. 首先检查要赋值的键名是否为 __proto__,这是一个特殊的键,需要特殊处理

    • 如果是 __proto__ 且存在 defineProperty 方法(即环境支持 Object.defineProperty),则使用 defineProperty 安全地设置该属性
    • 这么做是为了防止原型链污染攻击,保证操作的安全性
  2. 如果不是 __proto__ 或环境不支持 defineProperty,就直接使用赋值运算符 = 设置属性

    • 这是 JavaScript 中最基本的属性赋值方式

源码解析

让我们逐行分析 baseAssignValue 函数的实现:

javascript 复制代码
function baseAssignValue(object, key, value) {

函数定义,接收三个参数:

  • object:要修改的目标对象
  • key:要设置的属性名
  • value:要赋的值
javascript 复制代码
  if (key == '__proto__' && defineProperty) {

第一个条件检查,判断:

  1. 属性名是否为 __proto__(注意这里使用的是宽松相等 ==,所以会做类型转换)
  2. defineProperty 是否可用(在 Lodash 内部,defineProperty 是对 Object.defineProperty 的引用或自定义实现)

这个检查很重要,因为 __proto__ 是一个特殊属性,直接设置它可能导致原型链污染,产生安全风险。

javascript 复制代码
defineProperty(object, key, {
  configurable: true,
  enumerable: true,
  value: value,
  writable: true,
});

如果条件满足,使用 defineProperty 安全地定义该属性,并设置属性描述符:

  • configurable: true:允许属性被删除或重新配置
  • enumerable: true:允许属性在对象的属性枚举中出现
  • value: value:设置属性的值为传入的 value
  • writable: true:允许属性的值被修改

这种方式比直接赋值更安全,特别是对于 __proto__ 这样的特殊属性。

javascript 复制代码
  } else {
    object[key] = value;
  }

如果不是 __proto__ 属性或环境不支持 defineProperty,则直接使用标准的属性赋值语法。这是处理常规属性的快速路径。

原型污染问题

最新版的 Chrome 浏览器中暂时没有用代码验证出来

与 assignValue 的关系

baseAssignValueassignValue 的基础实现。assignValue 在调用 baseAssignValue 前会进行额外的检查:

javascript 复制代码
function assignValue(object, key, value) {
  var objValue = object[key];
  if (
    !(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
    (value === undefined && !(key in object))
  ) {
    baseAssignValue(object, key, value);
  }
}

assignValue 会:

  1. 检查对象是否已有同名且值相等的属性(使用 eq 判断)
  2. 检查值是否为 undefined 且对象上不存在该属性

只有当需要更新值时,才会调用 baseAssignValue 进行实际赋值操作。

总结

baseAssignValue 是 Lodash 内部的一个基础工具函数,用于安全地为对象设置属性值。

相关推荐
北海-cherish23 分钟前
vue中的 watchEffect、watchAsyncEffect、watchPostEffect的区别
前端·javascript·vue.js
AALoveTouch1 小时前
网球馆自动预约系统的反调试
javascript·网络
2501_915909061 小时前
HTML5 与 HTTPS,页面能力、必要性、常见问题与实战排查
前端·ios·小程序·https·uni-app·iphone·html5
white-persist2 小时前
Python实例方法与Python类的构造方法全解析
开发语言·前端·python·原型模式
新中地GIS开发老师3 小时前
Cesium 军事标绘入门:用 Cesium-Plot-JS 快速实现标绘功能
前端·javascript·arcgis·cesium·gis开发·地理信息科学
Superxpang3 小时前
前端性能优化
前端·javascript·vue.js·性能优化
左手吻左脸。3 小时前
解决el-select因为弹出层层级问题,不展示下拉选
javascript·vue.js·elementui
李白的故乡3 小时前
el-tree-select名字
javascript·vue.js·ecmascript
Rysxt_3 小时前
Element Plus 入门教程:从零开始构建 Vue 3 界面
前端·javascript·vue.js
隐含3 小时前
对于el-table中自定义表头中添加el-popover会弹出两个的解决方案,分别针对固定列和非固定列来隐藏最后一个浮框。
前端·javascript·vue.js