【JS面试题】如何通过闭包漏洞在外部修改函数中的变量

news2024/11/24 4:30:50

csdn动态图标

✍️ 作者简介: 前端新手学习中。

💂 作者主页: 作者主页查看更多前端教学

🎓 专栏分享:css重难点教学   Node.js教学 从头开始学习   ajax学习
前端面试题

文章目录

  • 什么是闭包
  • 如何在函数外部修改闭包中变量

什么是闭包

闭包这个东西对新人来说确实挺头疼的,MDN官方表述是这样的。

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)
的引用的组合。换而言之,
闭包让开发者可以从内部函数访问外部函数的作用域。
在 JavaScript 中,闭包会随着函数的创建而被同时创建

确实不是很好理解,那么我来通俗讲一下。

闭包其实就是指在函数内部定义一个函数,
内部定义的函数可以访问外部函数作用域中的变量,
这样就形成了一个封闭的作用域,被称作闭包。
即使外部函数已经执行完毕,闭包仍然可以访问这些变量。
这样我们就可以在函数外部 使用一个函数内的变量。
闭包还可以用来创建“私有”变量和方法,提高代码的封装性和安全性。


function outerFunction() {
//在函数内定义一个变量(函数作用域)
  const outerVariable = 0;
//函数内部再定义一个函数,并在这个函数中使用外层函数内定义的变量
  function innerFunction() {
  outerVariable++
    console.log(outerVariable);
  }

  return innerFunction;
}
//在函数执行完毕后用过一遍的变量一般都会被垃圾回收机制中的标记清除算法销毁掉。
//但是由于内部函数的引用所以没被销毁,通过内部函数我们可以访问到原本是函数作用域的变量,这样的弊端有时会引起内存泄漏,内存泄漏意思就是不需要使用的变量没有被垃圾回收机制回收。
const innerFunc = outerFunction();
innerFunc(); 1
innerFunc(); 2
//由于没被销毁回收,所以每次调用都会累加数量,除非再调用一次外部函数重新定义。
const innerFunc2 = outerFunction();
innerFunc()2; 1
innerFunc()2; 2
`` 

如何在函数外部修改闭包中变量

我们这里来看一道很nice的面试题。
题目

let o =(function () {
	var obj = {
	a:1,
	b:2,
};
return {
get:function(k){
	return obj[k]
}
}
})()

要求在不改变原代码的情况下,修改obj对象中的值。


我们使用这种闭包的原因就是为了使用函数值,并且保护函数值不被修改,就算要修改函数值也要定义一个修改函数,通过修改函数修改值。
但是这里面也没有修改函数 只有一个获取函数,它可以返回对象内属性的值。
我们通过这个函数可以得到对象内属性的值。

console.log(o.get('a')); 可以获取到1 obj中a属性的值。

我们想要修改这个对象,首先要获取对象,如何获取对象呢,从这个函数入手,
上面说了这个函数获取对象的属性没有做限制,除了这些基础方法之外,我们是不是还可以获取到对象原型上的方法。
可以尝试通过valueOf这个方法来获取到原对象的内容,Object 实例的 valueOf() 方法将 this 值转换成对象。在所有类型中都有这个方法 一般都会被隐式调用,比如

let a = 1;
console.log(a)   实际上就是a.valueOf()

我们可以通过这个方法,通过this指向来获取原对象。

像这样

console.log(o.get('valueOf')());
//不过结果报错了  并没有获取到,能看出是什么原因嘛,如果不能看出。
//修改试题中的获取函数,就能获取到结果,现在能看出什么原因了嘛。
let o =(function () {
	var obj = {
	a:1,
	b:2,
};
return {
get:(k)=>{
	return obj[k]()
}
}
})()

console.log(o.get('valueOf')); { a: 1, b: 2 }
//没错原因就是this指向问题,修改试题后的执行是这样的 obj[valueOf]()  this指向就是obj,可以拿到obj对象的内容,  没修改的话,return obj[valueOf] 返回来的函数,就是在全局环境执行的,this指向就是window所以报错 就跟Object.prototype.valueOf()一样。
//由于要求不能修改试题,所以我们只能找别的方法,但是这个思路是没有问题的。

最终的解决方法就是自己写方法
我们的目标还是想办法通过给的get函数获取原对象,我们可以这里在对象原型上自定义一个方法。

Object.defineProperty(Object.prototype,'getThis',{
    get(){
        return this;
    },
})
//我们直接在对象的原型上定义一个方法,只要调用getThis就会执行get函数  返回this。

//我们只需要执行就能得到原对象, 也就是return obj['getThis'] 函数内返回的this就是obj,这样就得到了对象。
console.log(o.get('getThis')); //{ a: 1, b: 2 }
//这时候就可以通过对象的引用特性,对原对象进行随意修改了

obj2=o.get('getThis')
obj2.a=3
obj2.b=1
console.log(o.get('getThis')); //{ a: 3, b: 1 }


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/994120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux--进程通信--管道通信

IPC是各种进程间通信方式的统称。 进程间通信:是指在不同进程之间传播或交换信息。 IPC的方式通常有: 单机:管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、 多机:Socket、Streams等 1、管道…

【计算机组成原理】十个问题带你走进计算机组成的世界

十个问题带你走进计算机组成的世界 你知道 a 1 2 这条代码是怎么被 CPU 执行的吗? 在计算机中,数据和指令是分开区域存放的,存放指令的区域的地方称为正文段,存放数据的区域称为数据段。 例如下图中,数据1和数据2…

Redis配置

关系型数据库和非关系型数据库 ①了解关系和非关系 关系型数据库 一个结构化的数据库,创建在关系模型基础上,一般面向于记录,包括Oracle、MySQL、SQL Server、Microsoft Access、DB2、postgreSQL等 非关系型数据库 除了主流的关系型数据库…

java 歌词解析 源代码, 在windows10下调试运行成功。

需要两个素材。 歌词与音乐.wav package week3.exam6;public class Info {private final String info;public Info(String info){this.infoinfo;}public String getInfo() {return info;}public String toString(){return info;} }package week3.exam6;public class Lyric ext…

华为云新用户云服务器优惠价格表

华为云服务器作为业界领先的云服务提供商之一,一直致力于为全球用户提供高效、稳定、安全的云服务。为了帮助新用户更好地了解华为云服务器的价格和优惠活动,本文将详细介绍华为云服务器对新用户的优惠价格表。 一、华为云耀云服务器L实例价格表 华为云…

JavaScript基础知识09——数据类型

哈喽,大家好啊,这里是雷工笔记,我是雷工。 数据类型比较常见,无论是对程序员,还是电气工程师来说,都再熟悉不过了,这里跟着教程了解一下,主要看跟自己以往在其他PLC,C#&a…

2023-09-09 LeetCode每日一题(课程表)

2023-09-09每日一题 一、题目编号 207. 课程表二、题目链接 点击跳转到题目位置 三、题目描述 你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中…

【牛客面试必刷TOP101】Day2.判断链表中是否有环和链表中倒数最后k个结点

作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:笔试强训选择题 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!&#xff…

python-jieba库

jieba库,python提供的中文分词函数库的第三方库,它可以将一段中文文本分割成中文词语序列。 安装jieba库 pip install jiebajieba的三个模式 全模式 - - - jieba.lcut(s,cut_allTrue) - - - 速度非常快,但有冗余数据 精确模式(…

窗口延时、侧输出流数据处理

一 、 AllowedLateness API 延时关闭窗口 AllowedLateness 方法需要基于 WindowedStream 调用。AllowedLateness 需要设置一个延时时间,注意这个时间决定了窗口真正关闭的时间,而且是加上WaterMark的时间,例如 WaterMark的延时时间为2s&…

嵌入式开发-绪论

目录 一.什么是嵌入式 1.1硬件系统 1.2软件系统 二.嵌入式应用场景 2.1消费电子 2.1.1智能家居 2.1.2影音 2.1.3家用电器 2.1.4玩具游戏机 2.2通信领域 2.2.1对讲机 2.2.2手机 2.2.3卫星 2.2.4雷达 2.3控制领域 2.3.1机器人 2.3.2采集器PLC 2.4金融 2.4.1POS…

快速文件复制与删除工具,将复制时文件夹里的原文件删除掉

无论是工作还是生活,我们都离不开文件的复制和管理。然而,手动复制文件不仅费时费力,而且容易出错。现在,我们为您推荐一款快速文件复制与删除工具,让您的文件管理更加高效! 首先,我们要进入文…

MybatisPlus分页插件使用

一. 效果展示 二. 代码编写 2.1 pom <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version> </dependency>2.2 添加配置类 Configuration MapperScan(…

推荐一款程序员截图神器!

快来看一下程序员必备的一款截图工具 今天就来和大家说一下作为程序员必备截图神器&#xff0c;几乎每一个程序员都会设置开机自启&#xff0c;因为这个截图功能太太太好用了&#xff01;&#xff01;&#xff01;只要你在键盘上按下F1就可以轻松截取整个屏幕&#xff0c;然后…

51单片机项目(9)——基于51单片机的电子琴设计

简易电子琴设计设计内容: 1.用矩阵键盘代表琴键&#xff0c;至少能弹出8个音符&#xff0c;分别是:音符1.23.4.,5,6, 2.键按下的时间长短表征节拍的长短&#xff0c;用蜂鸣器发出声音 3.数码管显示出当前音符 4.音量可调 &#xff08;代码及其工程文件放在最后&#xff09; …

vue中的几种name属性

vue中的几种name属性 组件名name name选项 export default{name:xxx } // 获取组件的name属性 this.$options.namevue-devtools调试工具里显示的组件名称&#xff1b; 未配置name选项&#xff0c;就是组件的文件名&#xff1b; vue3配置name通过defineOptions()函数 de…

msvcp110.dll是什么意思与msvcp110.dll丢失的解决方法

电脑突然提示msvcp110.dll丢失&#xff0c;无法执行此代码。导致软件无法打开运行&#xff0c;这个怎么办呢&#xff1f;我在网上找了一天的资料&#xff0c;终于把这个问题彻底处理好&#xff0c;也弄清楚了msvcp110.dll丢失的原因及msvcp110.dll丢失修复方法&#xff1f;现在…

20230909java面经整理

1.java常用集合 ArrayList动态数组&#xff0c;动态调整大小&#xff0c;实现List接口 LinkedList双向链表&#xff0c;实现list和queue接口&#xff0c;适用于频繁插入和删除操作 HashSet无序&#xff0c;使用哈希表实现 TreeSet有序&#xff0c;使用红黑树实现 HashMap无序&…

FPGA开发

https://www.enclustra.com.cn/?bd_vid11435475462206745180 https://www.monolithicpower.cn/design-tools/design-tools/llc-design-tool.html https://www.elecfans.com/article/88/143/2012/20120718280641_2.html

[JAVAee]IP数据包的组包与分包

目录 数据包是什么? 数据包的结构 数据包/分组与分组交换 分包是什么?为什么需要分包呢? 组包是什么? 分包组包过程中和哪些 IP 报头字段有关联? 本篇文章主要围绕三个问题来展开: 为什么要分包?分包组包过程中和哪些 IP 报头字段有关联组包时如何保证数据的顺序和…