【趣味JavaScript】我的天! 居然工作了5年的前端开发都不知道eval函数其中居然暗藏玄机!

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: JavaScript中的eval函数

🚀 个人主页 极客小俊
✍🏻 作者简介:web开发者、设计师、技术分享博主
🐋 希望大家多多支持一下, 我们一起进步!😄
🏅 如果文章对你有帮助的话,欢迎评论 💬点赞👍🏻 收藏 📂加关注

2.png

eval()函数介绍

首先你要知道在JSeval()函数是用来干嘛的!

它主要的功能就是将一个JS字符串解析,然后把它作为脚本代码来执行, 要知道字符串始终就是字符串是不能被直接执行的!

有了eval()函数就可以做到, 它的使用语法也很简单!

eval(字符串参数);

参数解释

传递的参数其实是要执行的 JavaScript代码字符串形式!

它的返回值也就是通过计算字符串得到可执行JS代码脚本

举个栗子

这里有一段代码

var code='var x=10;var y=20;console.log(x*y)';

如果直接执行或打印上面的code变量 那么只能直接输出这个字符串

如图
3.png

并且从字符串中的内容上看,很明显是一段JS代码

那么我们就可以使用eval()函数 来让它变成一个可执行的JS脚本

代码如下

var code='var x=10;var y=20;console.log(x*y)';
eval(code);

如图
4.png

eval()函数特别的使用方法以及原理

按照以上这样操作,我们只要把可执行的JS字符串丢给eval()函数不就行了吗?

那为什么有些时候还要加什么小括号()?

也就是为什么还要加()变成 eval('('+变量名+')')呢? 很多新手会在这里犯困惑!

那是因为如果字符串中的语法不正确,eval() 函数会抛出语法错误

w3c文档上也有明确的说明

如图

5.png

那到底如何来理解这个意思呢? 什么叫不是合法的表达式和语句呢?

举个栗子

var data ='{"张三"}';
console.log("类型为:"+typeof data);
console.log(eval(data));

以上打印结果如下图:

6.png

但是如果我写成以下这样就会给你报一个SyntaxError语法错误的提示!

如图

7.png

可是你可能会想,这不就是我们常见的JSON数据吗,虽然是字符串, 不能直接使用,但是使用eval()函数处理以下应该可以直接调用了呀,可为什么会报错呢?

原理分析

首先JSON是一种数据格式,它用于存储交换数据用的,这没问题吧!

JSON中,数据被表示为键值对,这里的之间用冒号分隔,键值对之间用逗号分隔

并且整个数据被包含在大括号{}当中,这也是JSON数据格式标准 也没问题对吧!

可是呢eval()函数会把这个字符串{......}当成一个Javascript语句块来处理, 那么显然这样解析就会报错!

我们平常写JS语句块都是以下的方式

for(){
   
   
    ..语句块..
}

if(){
   
   
    ..语句块..
}

while(){
   
   
    ..语句块..
}

这些都是语句块,也可以叫复合语句块

复合语句块是指由多个语句组成的语句块,它们通常被包含在一对花括号{....}

在开发中,复合语句块通常用于控制程序的流程

例如上面说到的: if、for、while 等语句的语句体就是一个复合语句块

复合语句块可以包含变量定义、表达式、控制语句等多种语句,

这些语句将按照顺序依次执行,直到复合语句块的结尾处!

那么你有见过以下这样的复合语句块块吗?

{
   
   
    "username":"zhangsan"
}

我们来运行看看效果

如图
8.png

那么很明显,从JS基本复合语句块的语法上,这就不能这样写对吧! 从JS语句的语法上讲不通呀!

所以说刚刚我们目的是让eval()函数JSON字符串解析为一个对象,而不是解析为语句块 明白了吧!

你也可以理解为是一种强制性的转换成表达式来进行表示!

如果我们不加括号,那么eval()函数就可能会将 这个JSON字符串解析为JS语句块的形式来进行执行,那语句块按照这样取写肯定是错误的语法呀,从而抛出语法错误!

那么就像上面的案例一样我们也可以让它正常执行成为一个JSON对象

代码如下

({
   
   
    "username":"zhangsan"
})

给它加上一个()括号 嗯嗯 这里非常的精妙!

加了()括号以后就表示一个整体, 让JS引擎知道这是一个JSON对象而非一个语句块, 自然就不会报错了!

我们也可以赋值给一个变量,把这个JSON对象保存起来进行调用了!

var test=({
   
   
    "username":"zhangsan"
});
console.log(test.username);

如图

9.png

所以{..}这种对象写法形式,不加外层的小括号,会被识别为JS代码块开始结束标记

注意

那这个时候可能就有人要问了, 为什么我不加这个小括号()也可以正常执行这个JSON对象呢?

代码如下

var test={
   
   "username":"zhangsan"};
console.log(test.username);

如图

10.png

分析解释

对,根据JSON的语法定义上来说这是没错, 并且你也把这一个整体赋值给了一个变量进行保存!

这跟加一个小括号() 一个道理, 明白了吧! JS引擎没有单一的把这{...}中的内容看成是一个语句块

而是把这一堆东西,赋值给了一个变量成为整体!

eval()函数使用心得体会

到这里你再次去理解eval()函数在处理字符串的时候,里面还要加一个小括号是不是就清晰很多了!

eval()函数只能接受JS代码作为参数,而不能接受JSON格式字符串作为参数

因此,当你将一个JSON格式的字符串传递给eval()函数时,它会抛出语法错误

eval()函数不是你想传递一个字符串就一定能给你正确的进行解析成可执行的代码!

需要你去观察你传递的字符串信息是否合理合法, 这也很好的解释了w3c文档中提到的不是合法的表达式和语句传递给eval()函数是会报错的!

w3c文档上其实也有明确的规定, 在处理JSON字符串的时候,最好要写成以下方式:

代码如下

eval('('+jsondata+')');

这样写的目的是为了让代码更加清晰,更容易理解!

如图
11.png

举个栗子

我们假设一个JSON字符串数据如下:

var data ='{"username":"张三","age":"20","company":"阿里巴巴"}';
eval(data);

这里直接使用eval()函数解析这个JSON字符串显然不能直接解析成JSON对象, 因为刚刚上面我说过了,这里很明显把这个JSON字符串解析成了JS语句块,直接报错!

如图

12.png

那么我们可以给这个JSON字符串直接加上一个小括号()看看

代码如下

var data ='({"username":"张三","age":"20","company":"阿里巴巴"})';
var result=eval(data);
console.log(typeof result);
console.log(result);

如图

13.png

这里就是用了小括号()JS引擎把这一堆字符串当成一个整体来看待!

也就是我们在JSON字符串的两端添加括号,就可以将其转换为一个整体的JavaScript表达式

并将结果存储在变量中。现在这个变量是一个JS对象,我们可以使用它来访问JSON数据的属性了!

如果当你不加括号的时候的时候{}会被解释成一个复合语句块

所以你经常可能会见到在使用eval()函数解析JSON字符串的时候会写成eval('('+json+')');这个样子

扩展

其实也不用那么麻烦, 直接使用JSON.parse()函数就可以解决这个问题了,要解析JSON字符串直接就用这个,最方便!

var data ='{"username":"张三","age":"20","company":"阿里巴巴"}';
var result=JSON.parse(data);
console.log(typeof result);
console.log(result);

效果跟上面是一样的!

eval()函数应用场景

我们可能经常会在ajax提取后端数据的时候,会获取到一个json数据,那么可能这个json数据是一个字符串,

当你拿到之后不能直接使用, 如果直接使用eval()函数就会报错或者打印不出数据返回出undefined等等结果!

所以要再eval()函数里面加一个小括号

如图
14.png

相关文章
|
1月前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
27天前
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
springboot解决js前端跨域问题,javascript跨域问题解决
|
29天前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
42 5
|
27天前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
68 1
|
1月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
36 4
|
1月前
|
资源调度 前端开发 JavaScript
vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
【11月更文挑战第10天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤,包括安装依赖、创建混淆脚本、修改 `package.json` 脚本命令、构建项目并执行混淆,以及在 HTML 文件中引用混淆后的文件。通过这些步骤,可以有效提高代码的安全性。
|
1月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
115 1
|
1月前
|
前端开发 JavaScript 开发者
除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
|
1月前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
41 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
1月前
|
前端开发 JavaScript 安全
vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
【11月更文挑战第7天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤。包括项目准备、安装 `javascript-obfuscator`、配置 Vite 构建以应用混淆,以及最终构建项目进行混淆。通过这些步骤,可以有效提升前端代码的安全性,防止被他人轻易分析和盗用。
170 0
下一篇
DataWorks