首页 > 编程语言 >java入门---作用域

java入门---作用域

时间:2024-07-16 20:58:03浏览次数:8  
标签:java 变量 .. 作用域 查询 --- obj foo

作用域:作用域是指在程序中定义变量的区域,该变量在该区域内可被访问。

1、关于作用域的两种查询

在JavaScript中编译器会用两种查询方式进行查询

一种是LHS查询;

一种是RHS查询;

俩个查询的含义是,当变量出现赋值操作在左侧时进行LHS查询,出现在右侧时进行RHS查询。

详细的讲就是RHS查询就是简单的查找某个变量的值,而LHS查询则是查询变量的容器本身,从而对其赋值。

当然在代码查询中对它俩的区别也很重要.

在变量还没有声明(在任何作用域都无法找到该变量)的情况下,这两种查询的行为是不一样是。

参考下面的代码:

function foo(a){
consle.log(a+b);
b=a;
}
foo(2);

第一次b进行RHS查询时是无法找到该变量的。也就是说,这是一个“未声明”的变量,因为在任何相关的作用域中都无法找到它,那么RHS查询就会让引擎就会抛出ReferenceError异常

相较之下,当引擎执行LHS查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎。


function foo(a) {

var b=a*2;

function bar(a) {

console.log(a,b,c);

}

bar(b*3);

}

foo(2);  //2,4,12

一个简单的小程序;但这个例子中有3个逐级嵌套的作用域;

(1)包含整个全局作用域,只有一个标识符:foo;

(2)包含foo所创建的作用域,只有三个标识符:a,bar,b;

(3)包含着bar所创建的作用域,只有一个标识符:c;

2、欺骗语法

词法作用域完全由写代码期间函数所声明的位置来定义,能在运行时来“修改”词法作用域的方法叫做欺骗;下面用两个关键字来做欺骗。

注意:欺骗词法作用域会导致性能下降,所以在代码使用这两种机制并不是什么好主意。

2.1  eval

eval(..)函数可以接受一个字符串为参数,并将其中的内容视为好像在书写时就存在于程序中这个位置的代码。

function foo(str,a){
eval(str);//欺骗
console.log(a,b);
}
var b=2;
foo("var b=3;",1);//1,3

eval(..)调用中的“var b=3;”这段代码会被当作本来就在那里一样来处理。由于那段代码声明了一个新的变量b,因此它对已经存在的foo(..)的词法作用域进行了修改。事实上,和前面提到的原理一样,这段代码实际上在foo(..)内部创建了一个变量b,并遮蔽了外部(全局)作用域中的同名变量。

当consle.log(..)被执行时,会在foo(..)的内部同时找到a和b,但是永远也无法找到外部的b,因此会输出“1,3”而不是正常情况下会输出的“1,2”。

2.2  with

JavaScript中;另一个难以控制的用来欺骗词法作用域的功能的with关键字。

with通常被当作重复引用同一个对象中多个属性的快捷方式,可以不需要重复引用对象本身。

比如:

var obj={
a:1,
b=2,
c:3
};
//单调乏味的重复"obj"
obj.a;
obj.b;
obj.c;
//简单的快捷方式
with(obj){
a=3;
b=4;
c=5;
}

但实际上这不仅仅是为了方便地访问对象属性。考虑下面代码:

function foo(obj){
  with(obj){
    a=2;
  }
}
    var o1={
      a:3
          };
    var o2={
      b:3
         };
foo(o1);
consle.log(o1.a); // 2
foo(o2.a);
consle.log(o2.a); //undefined
console.log(a); // 2---a被泄露到全局作用域上了

   这个例子中创造了o1和o2两个对象。其中一个具有a属性,另一个没有。foo(..)接受了obj的参数,该参数是一个对象引用,并对这个对象引用执行了with(obj){..}。在with块内部,我们写的代码看起来只是对变量a进行简单的词法引用,实际上就是一个LHS查询所引用的,并将2赋值给它。
   当我们将o1传递进去,a=2赋值操作找到了o1.a并将2赋值给它,这在后面的console.log(o1.a)中可以体现。而当o2传递进去,02并没有a属性,因此不会创建这个属性,o2.a保持undefined。

总结:eval(..)函数如果接受了一个或多个声明的代码,就会修改其所处的词法作用域,而with声明实际上是根据你传递给它的对象凭空创建了一个全新的词法作用域。

3、函数作用域

函数作用域的含义:属于这个函数的全部变量都可以在整个函数的范围内使用及复用。

举个例子

function foo(a) {
var b=2;
function bar() {
//.....
 }
var c=3;
}

由于标识符a、b、c和bar都附属于foo(..)的作用域,因此无法从foo(..)的外部对它们进行访问。也就是说,这些标识符全都无法从全局作用域中进行访问,因此下面的代码会导致ReferenceError错误:

bar();  //失败
console.log(a,b,c);   //三个全都失败

3.1 隐藏和避免冲突

JavaScript中的隐藏和C语言中的主函数与子函数差不多

特征一:引申于最小特权原则(指在软件设计中,应该最小限度地暴露必要内容,而将其他内容都“隐藏”起来)就是创建一个作用域将一段代码嵌套起来,使这段代码所声明的变量变成私有;

特征二:避免同名标识符之间的冲突;

标签:java,变量,..,作用域,查询,---,obj,foo
From: https://blog.csdn.net/qq_63698880/article/details/136722123

相关文章

  • 花几千上万学习Java,真没必要!(九)
    while循环:测试代码1:packagetestwhile.com;publicclassTestWhile{publicstaticvoidmain(String[]args){inti=0;while(i<5){System.out.println("当前循环次数:"+i);i++;}}}测试代码2......
  • c语言-逻辑运算符和逻辑表达式
    一认识三个逻辑运算符    1.&&“逻辑与”一假则假 2.||“逻辑或”一真则真3.!“逻辑非” 逻辑与和逻辑或都是双目运算符,要求两个操作数;逻辑非为单目运算符优先级为!>算术运算符>关系运算符>&&和|| >赋值运算符  运算符可以通过括号展开或收缩......
  • js需要同时发起百条接口请求怎么办?--通过Promise实现分批处理接口请求
    如何通过Promise实现百条接口请求?实际项目中遇到需要发起上百条Promise接口请求怎么办?前言不知你项目中有没有遇到过这样的情况,反正我的实际工作项目中真的遇到了这种玩意,一个接口获取一份列表,列表中的每一项都有一个属性需要通过另一个请求来逐一赋值,然后就有了这份封装真......
  • Redis - 数据结构与底层实现
    一、Redis数据结构Redis支持五种主要数据结构:字符串(String)、列表(List)、哈希表(Hashe)、集合(Set)和有序集合(SortedSet)。这些数据结构为开发者提供了灵活的数据操作方式,满足了不同场景下的数据存储需求。字符串(Strings):最基本的数据类型,可以包含任何数据,如数字、字符串、二进制数据......
  • 中国白酒品鉴知识培训一-笔记
    一白酒文化白酒起源于农业 酒祖仪狄 杜康依傍长江而栖的四川、贵州,一直是我国白酒文化的重要发祥地和传承地。是舞动中国白酒金三角龙头,打造世界顶尖白酒的基地。我国是世界上最早酿酒的国家之一,对世界酿酒技术的发展作出了巨大贡献。酿造白酒离不开水、土、气、气、......
  • SQL常用数据过滤---IN操作符
     在SQL中,IN操作符常用于过滤数据,允许在WHERE子句中指定多个可能的值。如果列中的值匹配IN操作符后面括号中的任何一个值,那么该行就会被选中。以下是使用IN操作符的基本语法:SELECT column1, column2, ... FROM table_name WHERE column_name IN (value1, value2......
  • SQL常用数据过滤---IN操作符
    在SQL中,IN操作符常用于过滤数据,允许在WHERE子句中指定多个可能的值。如果列中的值匹配IN操作符后面括号中的任何一个值,那么该行就会被选中。 以下是使用IN操作符的基本语法:SELECTcolumn1,column2,...FROMtable_nameWHEREcolumn_nameIN(value1,value2,...); ......
  • 数据库 -- DDL
    DDL,全称DataDefinitionLanguage,是数据库管理系统中的一种语言,用于定义和管理数据库中的数据结构。DDL主要包括以下几种语句:1、CREATE:用于创建数据库、表、索引等数据库对象。2、ALTER:用于修改数据库、表、索引等数据库对象。3、DROP:用于删除数据库、表、索引等数据库对......
  • 快速上手 Caffeine:Java 缓存库初学者指南
    一、背景简介:Caffeine是一个高性能的Java缓存库,旨在为现代应用程序提供快速、高效的缓存解决方案。它由GoogleGuavaCache的创始人之一开发,具备基于时间的过期、基于大小的回收、异步加载、统计信息等多种特性。Caffeine的性能有多么强大呢?以下是官方给出的基准测试......
  • Java SE 总结
    目录1初始Java2数据类型与变量3运算符4程序逻辑控制5方法的使用6数组的定义与使用7 Java类和对象8继承和多态9抽象类和接口10Java中String类11Java异常1初始JavaJDK,JRE,JVMJava代码书写注释标识符关键字标识符:在程序中由用户给类名......