首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如果你没有用var声明它或者它不是参数,为什么在函数的某些情况下不改变全局变量?

这个问题涉及到JavaScript中的变量作用域和函数作用域的概念。在JavaScript中,变量的作用域分为全局作用域和函数作用域。全局作用域中的变量可以在整个程序中被访问和修改,而函数作用域中的变量只能在函数内部被访问和修改。

当在函数内部使用一个变量时,JavaScript会首先在函数作用域中查找该变量,如果找不到,则会继续在全局作用域中查找。如果在全局作用域中也找不到,则会抛出一个错误。

在函数内部,如果使用了一个未声明的变量,则会默认创建一个全局变量。这是因为在函数作用域中没有找到该变量,因此JavaScript会在全局作用域中创建一个新的变量。

如果在函数内部使用了一个已经声明的全局变量,则会修改全局变量的值。这是因为在函数作用域中找到了该变量,因此会直接修改该变量的值。

如果在函数内部使用了一个未声明的变量,并且使用了var关键字声明,则会在函数作用域中创建一个新的变量。这是因为使用了var关键字,因此该变量的作用域被限制在函数作用域中,不会影响全局作用域中的变量。

因此,如果在函数内部使用了一个未声明的变量,并且不使用var关键字声明,则会默认创建一个全局变量。这是因为在函数作用域中没有找到该变量,因此JavaScript会在全局作用域中创建一个新的变量。如果该变量是一个参数,则不会创建全局变量,因为在函数作用域中已经找到了该变量。

总之,在函数内部使用未声明的变量时,需要注意变量的作用域和作用域链的概念,以避免意外创建全局变量。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

「译」JavaScript 究竟是如何工作的?(第二部分)

内存堆 image.png Orinoco 的 logo:V8 的垃圾回收器 每当你在 JavaScript 程序中定义了一个变量、常量或者对象时,你都需要一个地方来存储它。这个地方就是内存堆。...下面是一些会导致你的程序出现内存泄漏的常见错误: 全局变量:如果你不断地创建全局变量,不管有没有用到它们,它们都将滞留在程序的整个执行过程中。如果这些变量是深层嵌套对象,将会浪费大量内存。...var a = { ... } var b = { ... } function hello() { c = a; // 这是一个你没有意识到的全局变量 } 如果你试图访问一个此前没有声明过的变量...递归可以大幅度地减少执行算法所花费的时间(时间复杂度),不过它的理解和实施较为复杂。 下面的例子中,基本事件永远不会执行,lonley 函数在没有返回值的情况下不断地调用自身,最终会导致栈溢出。...事件循环就是用来发挥这个作用的。 事件循环 到现在为止,我们谈到的内容大多包含在 V8 里面,但是如果你去查看 V8 的代码库,你会发现它并不包含例如 setTimeout 或者 DOM 的实现。

50110

Python全网最全基础课程笔记(二)——变量

以至于为什么要写的这么详细:自己也是学过Python的,很多新手只是简单的过一篇语法,其实对于一个知识点的底层逻辑和其他使用方法以及参数详情根本不是很了解,这就导致学完很容易忘记,而且在实战过程中也是半知半解...赋值与传递:当不可变对象被赋值给另一个变量时,或者作为函数参数传递时,实际上是在传递对象的引用(或者说是对象的“身份”或“内存地址”的副本)。...但是,在函数内部直接修改全局变量需要特别注意,因为默认情况下,在函数内部赋值会创建一个新的局部变量(如果变量名已存在)或一个新的全局变量(如果变量名不存在于全局作用域中)。...globally" print(global_var) # 输出: I was modified globally 注意,如果在函数内部使用global关键字声明全局变量的话,最好要在函数的最开始进行使用...,例如global 声明了global_var全局变量,但是在声明之前,global_var就在函数中被使用到了,就会出现报错的。

5610
  • 56 道高频 JavaScript 与 ES6+ 的面试题及答案

    首先,所有的全局变量都是 window 的属性,语句 var a = 1; 等价于 window.a = 1; 你可以用如下方式来检测全局变量是否声明:"变量名称" in window。...澄清一下,函数声明是如下这样的代码: function functionName(arg1, arg2){ //函数体 } 如下不是函数,而是函数表达式,相当于变量赋值: var functionName...null 典型用法是: 作为函数的参数,表示该函数的参数不是对象。 作为对象原型链的终点。 当声明的变量还未被初始化时,变量的默认值为 undefined。...情况四:apply 调用 apply() 是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此,this 指的就是这第一个参数。...所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值

    91140

    JavaScript 闭包详解

    闭包函数可以访问[包裹其的函数]内的各种参数和变量,即便外部函数已经执行完毕.(至于为什么请看下文)....一、为什么要闭包 使外部得以访问函数内部的变量; 避免全局变量的使用,防止全局变量污染(匿名函数); 让某些关键变量得以常驻内存,免于被回收销毁(闭包函数); ---- 二、让某些变量得以常驻内存 我们需要将立即执行函数与闭包结合...,直到确认子函数不会再被调用(子函数被删除或者失去指针)为止; 类比一下,如果你学过webpack的话,应该会知道webpack在打包一个文件的时候会把这个文件依赖的所有文件一起打包,就是为了防止使用的时候出问题...; 可见立即执行函数在保存变量时泛用性比普通函数强; 三、让外部得以访问函数内变量 外部访问函数内变量跟立即执行函数没什么必然关系,不使用立即执行函数也可以进行保存,上面说到的结合立即执行函数的写法只是针对某些特殊情况下无法依据需求保存变量的问题...引擎发现你用一个小括号结束了你的函数,它觉得这是错的.

    44220

    56 道高频 JavaScript 与 ES6+ 的面试题及答案

    首先,所有的全局变量都是 window 的属性,语句 var a = 1; 等价于 window.a = 1; 你可以用如下方式来检测全局变量是否声明:"变量名称" in window。...澄清一下,函数声明是如下这样的代码: function functionName(arg1, arg2){ //函数体 } 如下不是函数,而是函数表达式,相当于变量赋值: var functionName...null 典型用法是: 作为函数的参数,表示该函数的参数不是对象。 作为对象原型链的终点。 当声明的变量还未被初始化时,变量的默认值为 undefined。...情况四:apply 调用 apply() 是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此,this 指的就是这第一个参数。...所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值

    1.1K10

    es6中的Let和Const详解

    (某些实现可能不报错),是因为参数x默认值等于另一个参数y,而此时y还没有声明,属于“死区”。...使用let声明变量时,只要变量在还没有声明完成前使用,就会报错。上面这行就属于这个情况,在变量x的声明语句还没有执行完成前,就去取x的值,导致报错”x 未定义“。...// 不会报错,各个块级作用域之间不互相影响 不能在函数内部重新声明参数。...不过,对于引用类型而言的话,它指的并不会对象的内容不变,而是对象的地址不变。也就是说,你可以修改对象的内部成员,但是你不可以修改该变量的地址。...// undefined 上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。

    56130

    ES6语法学习(let与var区别、块级作用域、const命令)

    console.log(i); } } a[6]();//6 思考:如果每一轮循环的变量i都是重新声明的,那么它怎么知道上一轮循环的值从而进行计算出本轮循环的值呢?...例1:下面的代码中,存在全局变量tmp,但是块级作用域中let又声明了一个全局变量tmp,导致后者绑定这个块级作用域,所以在let声明变量之前,对tmp赋值就会报错 var tmp = 123;...例:下面的函数中有两个代码块,都声明了变量n,运行后输出5,这表示外层代码块不受内层代码块的影响,如果使用var定义变量n,最后输出的值就是10 function f1() { let...下面两种函数声明在ES5中都是非法的,但是浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持了在块级作用域中声明函数,因此下面两种情况实际上都能运行,并不会报错。...但是对于引用类型的数据(对象、数组),变量指向的内存地址保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的这是不能控制的,因此,将一个对象声明为常量时需要非常小心。

    1.1K00

    我们是80后 golang入坑系列

    在Golang当中,本地的定义是按照函数或者语义块来区分的。只要在一个函数中定义的变量,或者在一个语义块中定义的变量都是本地变量。...与本地变量相对应的就是全局变量。 只要是在函数外部定义的都属于全局变量。...因为我们说过变量的声明方式有“var"和”:="两种。如果不小心写了个" g:=a+b"。虽然对最终的结果没有影响,但意思已经改变了,变成了在main函数中重新创建了一个g变量。...虽说全局变量也是变量,但全局变量的声明只能通过var来实现。...参数变量可以声明之后不使用。这点尤为明显,如果声明了一个本地变量,但自始至终都没有用到。编译时会提示删除这个变量。而参数变量,无论函数内部有没有用到,都不会提示。

    63270

    浏览器的内存泄漏场景、监控以及分析

    意外的全局变量 全局变量的生命周期最长,直到页面关闭前,它都存活着,所以全局变量上的内存一直都不会被回收 当全局变量使用不当,没有及时回收(手动赋值 null),或者拼写错误等将某个变量挂载到全局变量时...遗漏的 DOM 元素 DOM 元素的生命周期正常是取决于是否挂载在 DOM 树上,当从 DOM 树上移除时,也就可以被销毁回收了 但如果某个 DOM 元素,在 js 中也持有它的引用时,那么它的生命周期就由...这个能看到的内容很少,比较简单,目的也很明确,就是一段时间内,都有哪些操作在申请内存,且用了多少 总之,这些工具并没有办法直接给你答复,告诉你 xxx 就是内存泄漏的元凶,如果浏览器层面就能确定了,那它干嘛不回收它...是吧,即使周期性调用 replaceThing 函数,函数内的局部变量 o 即使存储着上个全局变量 t 的值,但毕竟是局部变量,函数执行完毕,如果没有外部持有它的引用,也就可以被回收掉了,所以最终内存就只剩下全局变量...,与最开始的区别就在于,至少在 unused 函数执行后,就可以释放掉而已 其实,这里应该考虑的代码有没有问题,为什么需要局部变量存储,为什么需要 unused 函数的存在,这个函数的目的又是什么,如果只是为了在将来某个时刻用来判断上个全局变量

    3.5K41

    JavaScript的IIFE(即时执行方法)

    假设有一个需求,每次调用函数,都返回加1的一个数字(数字初始值为0) 【1】全局变量   一般情况下,我们会使用全局变量来保存该数字状态 var a = 0; function add(){ return...这是因为在javascript代码解释时,当遇到function关键字时,会默认把它当做是一个函数声明,而不是函数表达式,如果没有把它显视地表达成函数表达式,就报错了,因为函数声明需要一个函数名,而上面的代码中函数没有函数名...以上便是立即执行函数+闭包的作用。 我为什么更愿意称它是“立即执行函数”而不是“自执行函数” IIFE的称谓在现在似乎已经得到了广泛推广(不知道是不是原文作者的功劳?)...{ arguments.callee(); };   // 这可能也算是个自执行匿名函数,但仅仅是foo标志引用它自身 // 如果你将foo改变成其它的,你将得到一个used-to-self-execute...// 该函数返回一个对象,包含你要暴露的属性 // 如下代码如果不使用立即执行函数,就会多一个属性i // 如果有了属性i,我们就能调用counter.i改变i的值 // 对我们来说这种不确定的因素越少越好

    1.5K50

    Javascript 严格模式详解

    4.1 全局变量显式声明 在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。...某些情况下,只允许静态绑定。也就是说,属性和方法到底归属哪个对象,在编译阶段就确定。这样做有利于编译效率的提高,也使得代码更容易阅读,更少出现意外。 具体来说,涉及以下几个方面。..."use strict";   var o = {     p: 1,     p: 2   }; // 语法错误 (2)函数不能有重名的参数 正常模式下,如果函数有多个重名的参数,可以用arguments..."use strict";   var n = 0100; // 语法错误 4.8 arguments对象的限制 arguments是函数的参数对象,严格模式对它的使用做了限制。...为了与新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数。

    1.2K80

    Javascript 严格模式 “use strict”

    4.1 全局变量显式声明 在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。...某些情况下,只允许静态绑定。也就是说,属性和方法到底归属哪个对象,在编译阶段就确定。这样做有利于编译效率的提高,也使得代码更容易阅读,更少出现意外。 具体来说,涉及以下几个方面。...”use strict”;   var o = {     p: 1,     p: 2   }; // 语法错误 (2)函数不能有重名的参数 正常模式下,如果函数有多个重名的参数,可以用arguments...”use strict”;   var n = 0100; // 语法错误 4.8 arguments对象的限制 arguments是函数的参数对象,严格模式对它的使用做了限制。...为了与新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数。

    96410

    【C语言】变量

    要区分变量名和变量值是两个不同的概念。         ② 变量顾名思义是可以发生改变的,当你定义一个变量的时候的值,到后面你想改变它的值还是可以发生改变的。        ...② 变量的声明一般情况下会有两种情况。 需要建立存储空间的。 int a = 0;//声明定义的时候就已经建立了存储空间 不需要建立存储空间的。...局部变量  概述在一个函数内部声明的变量是内部变量,它只在本函数内部有效。在本函数之外是不能使用的,这样的变量就是局部变量。         在某个函数或块的内部声明的变量称为局部变量。...概述在函数外部声明的就是全局变量,全局变量是定义在函数外部,通常是在程序的顶部。...全局变量在整个程序生命周期内都是有效的,在任意的函数内部能访问全局变量。全局变量可以被任何函数访问,也就是说全局变量在声明后整个程序中都是可用的。

    15910

    记住,永远都不要在 Flutter 中使用全局变量

    全局变量似乎是很棒的 Flutter 程序组件,因为它们被声明一次并且可以被程序中的每个函数访问。...以上所有原因都说明了为什么在 Flutter 中永远不应该使用全局变量。...如果删除一个全局变量,则必须搜索整个程序并重构每个有权访问已删除全局变量的函数。 2. 全局变量使单元测试变得痛苦 如果你更改了一个具有全局变量的模块,那么你将不得不为下一次测试重置它。...全局变量导致“面条”代码 由于程序中的每个函数都可以修改全局变量,因此很难跟踪更改。如果你正在构建一个大型应用程序,在 Flutter 中使用全局变量的情况会升级。...但是,有些开发人员会使用全局变量,因为他们在一个小团队中,并且在某些情况下不利于更改。 但是,无论应用程序的大小如何,当需要维护代码时,全局变量都会带来挑战。

    3.6K30

    React 语法之let和const命令

    变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。...function bar(x = y, y = 2) { return [x, y]; } bar(); // 报错 上面代码中,调用bar函数之所以报错(某些实现可能不报错),是因为参数x默认值等于另一个参数...如果确实需要,也应该写成函数表达式,而不是函数声明语句。...ES6的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。...undefined 上面代码中,全局变量a由var命令声明,所以它是全局对象的属性;全局变量b由let命令声明,所以它不是全局对象的属性,返回undefined。

    6.4K60

    C++知识概要

    存储在静态存储区,作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。...在函数返回类型前加 static,函数就定义为静态函数。函数的定义和声明在默认情况下都是 extern 的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。...) 派生类自己的构造函数 必须使用成员列表初始化的四种情况 当初始化一个引用成员时 当初始化一个常量成员时 当调用一个基类的构造函数,而它拥有一组参数时 当调用一个成员类的构造函数,而它拥有一组参数时...;clear()函数,只能清空内容,不能改变容量大小;如果要想在删除内容的同时释放内存,那么你可以选择 deque 容器 int main(){ vector vec(10, 0);...还可以采用通用算法 remove()来删除 vector 容器中的元素 采用 remove 一般情况下不会改变容器的大小,而 pop_back()与 erase()等成员函数会改变容器的大小,使得之后所有迭代器

    1.1K20

    JavaScript的工作原理:内存管理+如何处理4个常见的内存泄漏

    读取与写入可能是写入一个变量或者一个对象的属性值,甚至传递函数的参数。 Release when the memory is not needed anymore 大多数内存管理的问题都在这个阶段。...换句话说,GC 是不可预测的,无法确定何时会执行收集。这意味着在某些情况下,程序使用的内存要比实际需要的还多。另一个场景是,在特别敏感的应用中,那么一些短暂的暂停会显得特别明显。...但是,如果不使用 var 来声明它,则会创建一个冗余的全局变量。在上述情况下,这不会造成太大伤害。你肯定可以想象一个更具破坏性的场景。...如果必须使用全局变量来存储数据,请确保使用完成后将其指定为null或重新分配它。 2....当这种情况发生时,就会保留同一 DOM 元素的两份引用:一个在 DOM 树中,另一个在字典中。如果将来某个时候你决定要删除这些行,则需要让两个引用都不可达。

    86351

    JavaScript的工作原理:内存管理+如何处理4个常见的内存泄漏

    读取与写入可能是写入一个变量或者一个对象的属性值,甚至传递函数的参数。 Release when the memory is not needed anymore 大多数内存管理的问题都在这个阶段。...换句话说,GC 是不可预测的,无法确定何时会执行收集。这意味着在某些情况下,程序使用的内存要比实际需要的还多。另一个场景是,在特别敏感的应用中,那么一些短暂的暂停会显得特别明显。...但是,如果不使用 var 来声明它,则会创建一个冗余的全局变量。在上述情况下,这不会造成太大伤害。你肯定可以想象一个更具破坏性的场景。...如果必须使用全局变量来存储数据,请确保使用完成后将其指定为null或重新分配它。 2....当这种情况发生时,就会保留同一 DOM 元素的两份引用:一个在 DOM 树中,另一个在字典中。如果将来某个时候你决定要删除这些行,则需要让两个引用都不可达。

    83330

    前端面试(2)javascript

    首先需要声明你的类,然后访问它,否则像下面的代码会抛出一个 ReferenceError。...第二种场景,用来计数的循环变量泄露为全局变量(前面在重复声明中提到的): //上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。...Javascript 语言的特殊之处,就在于函数内部可以直接读取全局变量。 在函数外部自然无法读取函数内的局部变量,函数内部声明变量的时候,一定要使用 var 命令。...它一共运行了两次,第一次的值是 999,第二次的值是 1000。这证明了,函数 f1 中的局部变量 n 一直保存在内存中,并没有在 f1 调用后被自动清除。 为什么会这样呢?...所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值

    1.3K20
    领券