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 内部的一个基础工具函数,用于安全地为对象设置属性值。

相关推荐
程序员黑豆3 分钟前
鸿蒙应用开发之状态变化通知:@Watch 装饰器详解与实战
前端·harmonyos
swipe4 分钟前
13|(前端转全栈)支付成功不等于结束:回调、幂等、超时关单和状态竞争
前端·后端·面试
swipe17 分钟前
12|(前端转全栈)点击提交订单后,后端如何用事务守住价格、库存和订单?
前端·后端·面试
小林ixn21 分钟前
React + TypeScript 实战:从“类型体操”到“数据持久化”,一次讲透组件通信与副作用管理
前端·react.js·typescript
何时梦醒21 分钟前
React + TypeScript 企业级开发实战:从零搭建到组件架构演进
前端·react.js·全栈
Coffeeee22 分钟前
AGP9.0的主要变更项,给Gradle来一次大变样
android·前端·gradle
张元清26 分钟前
React useUpdateEffect Hook:跳过首次渲染(2026)
javascript·react.js
无人生还33 分钟前
从 Vue3 到 React · 快速上手系列第 7 篇:副作用与生命周期 —— watch/watchEffect 如何翻译为 useEffect
前端·vue.js·react.js
数聚天成DeepSData37 分钟前
外贸海关进出口数据去哪免费下载?从统计到明细的查找指南
linux·服务器·开发语言·前端·网络·人工智能·自然语言处理
半夜里咳嗽的狼43 分钟前
组件进侧栏就变形?用 CSS Container Queries 把响应式边界收回组件
前端·css