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

相关推荐
漫路在线22 分钟前
JS逆向-某易云音乐下载器
开发语言·javascript·爬虫·python
不爱吃糖的程序媛25 分钟前
浅谈前端架构设计与工程化
前端·前端架构设计
BillKu2 小时前
Vue3 Element Plus 对话框加载实现
javascript·vue.js·elementui
郝YH是人间理想2 小时前
系统架构设计师案例分析题——web篇
前端·软件工程
Evaporator Core2 小时前
深入探索:Core Web Vitals 进阶优化与新兴指标
前端·windows
初遇你时动了情3 小时前
html js 原生实现web组件、web公共组件、template模版插槽
前端·javascript·html
QQ2740287563 小时前
Soundness Gitpod 部署教程
linux·运维·服务器·前端·chrome·web3
前端小崔3 小时前
从零开始学习three.js(18):一文详解three.js中的着色器Shader
前端·javascript·学习·3d·webgl·数据可视化·着色器
哎呦你好3 小时前
HTML 表格与div深度解析区别及常见误区
前端·html
运维@小兵3 小时前
vue配置子路由,实现点击左侧菜单,内容区域显示不同的内容
前端·javascript·vue.js