问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
你好,欢迎来到懂视!登录注册
当前位置: 首页 - 正文

理解什么是JS作用域,闭包和基本的JS作用域面试题

发布网友 发布时间:2022-04-23 01:16

我来回答

2个回答

懂视网 时间:2022-04-29 15:02

与闭包有关的概念:变量的作用域和变量的生存周期。下面本篇文章就来给大家介绍一下JavaScript中变量的作用域及闭包,有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

一、变量的作用域

1、变量的作用域指变量有效的范围,与变量定义的位置密切相关,作用域是从空间的角度来描述变量的,也可以理解为变量的可见性。在某个范围内变量是可见的,也就是说,变量是可用的。【相关课程推荐:JavaScript视频教程】

2、按照作用域的不同,变量可分为全局变量和局部变量。

● 全局变量:在全局环境中声明的变量

● 局部变量:在函数中声明的变量

● 当函数在执行时,会创建一个封闭的执行期上下文环境,函数内部声明的变量仅可在函数内部使用,外部无法访问,而全局变量则在任何地方都可以使用

3、在函数中使用var关键字显示声明的变量是局部变量;而没有用var关键字,用直接赋值的方式声明的变量是全局变量

var m=8;
function f1(){
 var a1=10;
 console.log(m); //8
}
function f2(){
 var a2=20;
 console.log(m); //8
}
f1();
f2();

4、依赖变量作用域实现封装特性

(1)使用ES6提供的let
(2)通过函数来创建作用域:

var myObject=(function(){
 var _name="yian"; //私有变量
 return {
 getName:function(){ //公有方法
  return _name;
 }
 }
})();
console.log(myObject._name); //undefined
console.log(myObject.getName()); //yian

二、变量的生存周期

1、对于全局变量来说,其生命周期是永久的,除非主动销毁此全局变量;

2、对于在函数内用var关键字声明的局部变量来说,当退出函数时,这些局部变量即失去它们的价值,它们会随着函数调用的结束而被销毁

3、模仿块级作用域

(1)用作块级作用域的匿名函数:将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式,而紧随其后的另一对圆括号会立即调用这个函数。

(function(){
 //这里是块级作用域
})();

在匿名函数中定义的任何变量,都会在执行结束时被销毁

(2)先定义一个函数,然后调用它。定义函数的方式是创建一个匿名函数,并把这个匿名函数赋值给变量;而调用函数的方式是在函数的名称后添加一对圆括号。

var someFunction=function(){
 //这里是块级作用域
};
someFunction();

经典问题:

var nodes=document.getElementsByTagName("div");
for(var i= 0,len=nodes.length;i<len;i++){
 nodes[i].onclick=function(){
 console.log(i); //无论点击哪个div,最后弹出的结果都是5
 }
}

解释: div节点的onclick事件是被异步触发的,当事件被触发时,for循环早已结束,此时i 已经是5

解决办法:

法一:使用ES6中的let

法二:在闭包的帮助下,把每次循环的i值都封存起来

var nodes=document.getElementsByTagName("div");
for(var i= 0,len=nodes.length;i<len;i++){
 (function(x){
 nodes[i].onclick=function(){
  console.log(x);
 }
 })(i);
}

4、作用:读取函数内部的变量,并将这些变量的值始终保存在内存中

(1)封装变量:闭包可以把一些不需要暴露在全局的变量封装为“私有变量”,私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。

例:mult函数接收number类型的参数,并返回这些参数的乘积、

初始代码:

var cache={ };
var mult=function(){
 var args=Array.prototype.join.call(arguments,",");
 if(cache[args]){
 return cache[args];
 }
 var a=1;
 for(var i=0,len=arguments.length;i<len;i++){
 a=a*arguments[i];
 }
 return cache[args]=a;
};
console.log(mult(1,2,3)); //6
console.log(mult(3,4,5)); //60

使用闭包后:

var mult=(function(){
 var cache={ }; //加入缓存机制,避免相同参数的计算
 var calculate=function(){
 var a=1;
 for(var i= 0,len=arguments.length;i<len;i++){
  a=a*arguments[i];
 }
 return a;
 };
 return function(){
 var args=Array.prototype.join.call(arguments,",");
 if(args in cache){
  return cache[args];
 }
 return cache[args]=calculate.apply(null,arguments);
 }
})();

补充:in判断属性属于对象

var mycar = {make: "Honda", model: "Accord", year: 1998};
if ( "make" in mycar ){ //属性名必须是字符串形式,因为make不是一个变量
 document.write('true'); // 显示true
}
else{
 document.write('false');
}

(2)延续局部变量的寿命

例:使用report数据上报时会丢失30%左右的数据,原因是img时report中的局部变量,当report函数调用结束后,img局部变量随即被销毁

初始代码:

var report=function(src){
 var image=new Image();
 image.src=src;
};

使用闭包后(把img变量用闭包封装起来):

var report=(function(){
 var imgs=[ ];
 return function(){
 var image=new Image();
 imgs.push(image);
 image.src=src;
 }
})();

5、闭包和面向对象设计

闭包写法:

var extent=function(){
 var value=0;
 return {
 call:function(){
  value++;
  console.log(value);
 }
 }
}
var extent=extent();
extent.call(); //1
extent.call(); //2

面向对象写法一:

var extend={
 value:0,
 call:function(){
 this.value++;
 console.log(this.value);
 }
};
extend.call(); //1
extend.call(); //2

面向对象写法二:

var Extend=function(){
 this.value=0;
};
Extend.prototype.call=function(){
 this.value++;
 console.log(this.value);
};
var extend=new Extend();
extend.call(); //1
extend.call(); //2

6、闭包与内存管理

● 局部变量变量应该在函数退出时被解除引用,但如果局部变量被封闭在闭包形成的环境中,那么局部变量就会一直生存下去,即它会常驻内存。

● 使用闭包的同时比较容易形成循环引用,如果闭包的作用域链中保存着一些DOM节点,这就有可能造成内存泄漏。

● 解决循环引用带来的内存泄漏问题:把循环引用中的变量设为null。(将变量设置为null以为着切断变量与它之前引用的值之间的连接,当垃圾收集器下次运行时,就会删除这些值并回收它们占用的内存)

7、特点:

● 函数嵌套函数;

● 在函数内部可引用外部的参数和变量;

● 参数和变量不会以垃圾回收机制回收。

8、优点:避免全局变量的污染

9、缺点:会常驻内存,增加内存的使用量,使用不当会造成内存泄漏;闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存

10、创建闭包

写法一:

function a() { 
	var b=123; 
	function c(){
 	console.log(b+=1);
 } 
 return c;
}
var d=a();
d();

方式二:

function f1(){
 var num=10; //函数执行完毕,变量仍然存在
 var f2=function(){
 num++;
 console.log(num); //11
 };
 return f2;
}
var res=f1();
res();

● 解释:执行f1()后,f1()闭包内部的变量会存在,而闭包内部函数的内部变量不会存在,使得JavaScript的垃圾回收机制不会收回f1()占用的资源,因为f1()中内部函数的执行需要依赖f1()中的变量。

方式三:

function foo(x) {
 var tmp = 3;
 return function f2(y) {
 alert(x + y + (++tmp)); //17
 };
}
var bar = foo(3); //bar现在是一个闭包
bar(10);

练习题:

function f1(){
 var a=1;
 t=function(){
 a++;
 }
 return function(){
 console.log(a);
 }
}
var b=f1(); //返回值为一个匿名函数
b(); //1
t();
b(); //2

声明变量,若变量名称相同,就近原则:

var name="g";
function out(){
 var name="loc";
 function foo(){
 console.log(name);
 }
 foo();
}
out(); //name=loc

补充知识点:

1、JS中有哪些垃圾回收机制?

(1)引用计数:跟踪记录每个值被使用的次数。

● 当声明一个变量并将一个引用类型赋值给该变量时,该值的引用次数加1;

● 若该变量的值变为另一个,则该值引用次数减1;

● 若该值引用次数为0时,说明变量没有在使用,此值无法访问;

● 因此,可以将它占用的空间回收,垃圾回收机制会在运行时清理引用次数为0 的值所占用的空间。

● 在低版的IE中会发生内存泄漏,很多时候就是因为它采用引用计数得到方式进行垃圾回收(如果两个对象之间形成了循环引用,那么这两个对象都无法被回收)。

(2)标记清除:最常见的垃圾回收方式

● 当变量进入执行环境时,垃圾回收器将其标为“进入环境”,离开时标记为“离开环境”;

● 垃圾回收机制在运行时给存储在内存中的所有变量加上标记;

● 去掉环境中的变量及被环境中变量所引用的变量(闭包)的标记;

● 完成这些后仍存在的标记就是要删除的变量。

2、哪些操作会造成内存泄漏?

● 内存泄漏:指不再拥有或需要任何对象(数据)之后,它们仍然存在于内存中。

● 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为0(没有其他对象引用过该对象),或对该对象的唯一引用是循环的,那么该对象占用的内存立即被回收。

● 如果setTimeout的第一个参数使用字符串而非函数,会造成内存泄漏。

● 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)等会造成内存泄漏。

本文来自 js教程 栏目,欢迎学习!

热心网友 时间:2022-04-29 12:10

作用域:它是指对某一变量和方法具有访问权限的代码空间, 在JS中, 作用域是在函数中维护的。表示变量或函数起作用的区域,指代了它们在什么样的上下文中执行,亦即上下文执行环境。Javascript的作用域只有两种:全局作用域和本地作用域,本地作用域是按照函数来区分的。

闭包:在js中的我的理解就是函数嵌套函数,当内部函数在定义它的作用域的外部被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们.
使用闭包要注意:
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便
改变父函数内部变量的值。
理解什么是JS作用域,闭包和基本的JS作用域面试题

作用域:它是指对某一变量和方法具有访问权限的代码空间, 在JS中, 作用域是在函数中维护的。表示变量或函数起作用的区域,指代了它们在什么样的上下文中执行,亦即上下文执行环境。Javascript的作用域只有两种:全局作用域和本地作用域,本地作用域是按照函数来区分的。闭包:在js中的我的理解就是函数嵌...

什么是JS闭包?求详解

闭包是很多语言都具备的特性,在js中,闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等.在理解闭包以前.最好能先理解一下作用域链的含义,简单来说,作用域链就是函数在定义的时候创建的,用于寻找使用到的变量的值的一个索引,而他内部的规则是,把函数自身的本地变量放在...

前端:如何理解 JS 的作用域和作用域链?说说闭包的两个应用场景_百度知 ...

从上面的例子可以体会到作用域的概念,作用域就是一个独立的 地盘 ,让变量不会外泄、暴露出去。上面的name就被暴露出去了,因此, JS 没有块级作用域,只有全局作用域和函数作用域 。全局作用域就是最外层的作用域 ,如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局...

浅谈js中什么是封闭函数、闭包、内置对象

一、变量作用域变量作用域指的是变量的作用范围,javascript中的变量分为全局变量和局部变量1、全局变量:在函数之外定义的变量,为整个页面公用,函数的内部外部都可以访问。2、局部变量:在函数内部定义的变量,只能在定义该变量的函数内部访问,外部无法访问。函数内部访问变量时,先在内部查找是否有此变量...

js基础面试题61-70道题目

62.js 属于哪种作用域 参考答案:词法作用域(函数作用域)解析:参与互动 63.浮点数精度 参考答案:参考 参与互动 64.自执行函数? 用于什么场景?好处?参考答案:好处:防止变量弥散到全局,以免各种 js 库冲突。隔离作用域避免污染,或者截断作用域链,避免闭包造成引用变量无法释放。利用立即执行特性,...

如何理解js中的闭包

本次的这篇文章主要是和大家分享了如何理解js中的闭包 ,有需要的小伙伴可以看一下1、变量作用域要理解闭包,首先要理解javascript的特殊的变量作用域。变量的作用域无非就两种:全局变量和局部变量。javascript语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量...

js闭包的理解是什么

JS闭包是JS语言的一个重要特性,也是很多初学者面试必考的一道题目。它是指内部函数可以访问定义在外部函数中的变量和参数,即使外部函数已经返回,这些变量和参数仍然可以使用。这种特性使得JS编程语言更加灵活和强大,也是JS中常用的编程模式之一。闭包的应用场景非常广泛,比如在事件监听、回调函数、模块化...

js 闭包(面试题)

1. 闭包的本质就是在一个函数内部创建另一个函数。2 匿名函数作为fun的返回值被赋值给了f, 这时候相当于 f=function(){var n = 0 … }, 并且匿名函数内部引用着fun里的变量num,所以变量num无法被销毁, 而变量n是每次被调用时新创建的,所以每次 f 执行完后它就把属于自己的变量...

Js闭包的原理(图解)

要理解闭包,我们得先搞清楚以下几个概念:JS的作用域分两种:全局作用域、局部作用域(也可称为函数作用域)总的来说,Js作用域的一般机制就是:内部可访问外部的变量,外部无法访问内部的变量。那么这套作用域机制是如何实现的呢?答案是:通过作用域链 在Js中,每当一个函数被执行,都会产生三个...

JS中的闭包是什么?

我告诉你答案,你根本不需要知道闭包这个概念,一样可以使用闭包!闭包是JS函数作用域的副产品。换句话说,正是由于JS的函数内部可以使用函数外部的变量,所以这段代码正好符合了闭包的定义。而不是JS故意要使用闭包。很多编程语言也支持闭包,另外有一些语言则不支持闭包。只要你懂了JS的作用域,你自然而...

声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。
E-MAIL:11247931@qq.com
电表到进户这一段儿现老旧了。我出现在不在维修电工范围之内? 传祺gs7和gs8哪个好 精液不液化症怎么治好 深圳最高楼是那座,多少层 深圳最高的大厦是哪座 深圳最高的大厦叫什么大厦,地处什么区 北京华业鲲鹏商贸有限公司怎么样? 宜昌三峡制药有限公司简介 鲲鹏万里(厦门)石材贸易有限公司怎么样? 葫芦岛鲲鹏贸易有限公司怎么样? wps中给图片加题注,题注文字如何跟随图片移动? js 闭包逻辑面试题 前端面试:js闭包,为什么要使用闭包 梦见老鼠是什么预兆? 梦到好多老鼠在笼子里 外面有猫不出来 梦到一大群被困在笼子里的老鼠 梦见狗和老鼠被逮在一个笼子里是什么意思? 梦见捕捉到一只老鼠关进笼子里 梦见老鼠偷跑,在笼子里偷跑,一个大老鼠,一个小老鼠 我梦见老鼠吃了药,快死了.在笼子里我还打了它. 梦见一只大老鼠在笼子里面,梦见有人放了一个老鼠笼子,刚放好有一只大老鼠就钻进去了,被关在里面了 梦到好多大老鼠分别被关到笼子里,是什么意思呢 梦见老鼠被关在笼子里挨饿,请高人解答 周公解梦见老鼠被关进笼子里面 怎样做糯米肉丸子好吃? 自己怎么做糯米小丸子 四川糯米圆子的家常做法 如何做出营养美味的糯米丸子? 过年才能吃的糯米丸子,怎么做香甜软糯,孩子超爱吃? 糯米丸子怎么做好吃? WPS word里如何给图片写题注为2-1、2-2、3-1、3-2、3-3……之类的 ,并且在目录环节引用插入表目录 什么是JS闭包?求详解 求助:WPS中给图片加题注,却只能显示0.1??? wps/word 给同行的两个图片加题注 JS闭包是什么东西? 请问用wps如何自动插入题注? javascript怎么实现闭包 JavaScript闭包,什么是闭包,对闭包的理解 javascript的闭包是什么意思 有什么用 WPS中插入的图片后,怎么在图片上写字或是做重点标记? javascript的闭包问题 wps 环境下,在某一章中插入图的题注,编号变成了一.1,怎么让编号变成1.1... javascript闭包问题 javascript闭包是什么? javascript闭包题目的疑惑,是怎么回事? 电脑中的WPS文字题插入图片后,怎样才能为文档中所有图片应用基于“正文”样 JavaScript的闭包问题! JS闭包的概念 JavaScript 里的闭包是什么?应用场景有哪些 JavaScript闭包的3个问题
  • 焦点

最新推荐

猜你喜欢

热门推荐