Javascript入门基础——作用域

前言

Javascript属于是一种弱类型动态语言且在执行代码前是需要先编译的,且变量的查找会先从内到外的作用域中查找,不能从外到内查找。

什么叫弱类型动态语言呢?

当强类型动态语言声明一个变量时 var a:number=1 ,需要加上类型名(number),此时当你重新定义a='hello'时,此行代码无法运行,'hello'是字符串类型,而你定义的确实number类型,而弱类型动态语言声明一个变量时只需 var a=1,不需要加类型,并且当你修改a值时(a='hello'),可以成功修改的。

js 复制代码
var a =1
a='hello'
console.log(a);

# 在Javascript中什么是作用域?又包括哪几类? 作用域(Scope)是编程中用于确定在代码中访问变量的可见性和可访问性的概念。作用域规定了程序中变量的可见范围,以及在特定位置可以访问哪些变量。

作用域

一、全局作用域

在 JavaScript 中,位于函数之外的变量被称为全局变量,它们拥有全局作用域。这意味着全局变量可以在代码的任何地方被访问,包括函数内部和外部。

js 复制代码
  var a = 1;//全局变量 
  var b = 2;//全局变量 
  function foo() {
      console.log(a, b);
  }
  foo();

二、局部作用域

局部作用域是指在函数内部声明的变量,它们只能在函数内部访问,称为局部变量。

jsvar 复制代码
function foo() {
  var a = 2;//局部变量
  console.log(a);
  }
  foo();

三、块级作用域

块级变量声明周期 : 从大括号开始 -> 到大括号结束。

jsif(true){ 复制代码
    var a = 1;//全局变量
    let b = 2;//块级变量(块级作用域 :只在大括号内部起作用)
    console.log(a,b);//1,2
    
};

   console.log(a);//1
// console.log(b);// b is not defined

到这儿,各位小伙伴可能就不能理解了,为什么a和b都是在if语句中定义,但a是全局变量而b却是块级变量呢,这就引出了我们今天的另外一个知识点:var有声明提升的作用,将a=1提升到作用域的顶端,成为全局变量,而函数的声明则会整体提升,但let却没有声明提升这个功能,这在后续的讲解中将为大家介绍到let、const与var声明的区别!

什么是声明提升呢?

例如下面这段代码,当我们用正常思维逻辑来解释时,这段代码是不能让人理解的,正是声明提升以及执行前先编译这两个特点的存在,使得这段代码是可以运行的,但是得出来的结果是undefined,这并不意味着是错误,而是因为在执行console.log语句前,a并没有赋到值。

js 复制代码
console.log(a);
var a=1;

上面那段代码因为声明提升的原因,等同于下面这段代码,将a的声明提升到了最顶端,但是对于a的赋值却不能提升,这也是最终结果出现undefined的原因。

js 复制代码
var a
console.log(a);
a =1

let及const与var声明的区别

(一)let及const不能声明提升

还是拿上一段var定义的代码来说,将var替换成let以及const,分别调试看结果。

js 复制代码
console.log(a);
let a =1
js 复制代码
console.log(a);
const  a =1

从上面的两个调试结果我们可以看到,显示的是"cannot access 'a' before initialization",这是报错的意思,而var定义时却是说"undefined",说明let及const与var不同,var可以声明提升,而let及const不能声明提升。

(二)let及const的特点

let除了不能声明提升外,还不能同时定义两个相同的量,系统会出现报错,但用let声明一个变量,其可以修改值,下列代码中,将a的值修改为了hello。

js 复制代码
let a=1
a='hello'
console.log(a);

const同样不能声明提升且不能同时定义两个相同的量,但是const也不可以修改变量值,下列代码在运行中会出现报错。

js 复制代码
const a=1
a='hello'
console.log(a);

欺骗词法作用域

(一)eval()将原本不属于这行的代码放置这行

观察下列代码:

js 复制代码
var b = 2; // 被覆盖
function foo(str, a) {
	eval(str); // 欺骗
	console.log(a, b);//输出: 1, 3
}
foo("var b = 3;", 1);

为什么得出来的(a,b)会是1,3呢?这正时因为eval()函数的作用,foo()中,str对应"var b = 3",而a对应"1",但由于eval(str)产生了欺骗,将第三行的代码替换成了"var b = 3"使得b=2的值被b=3覆盖,所以当console.log输出时,会是1,3。

(二)with()当修改对象中不存在的属性时,该属性会泄露到全局成为全局变量

观察下列代码:

js 复制代码
function foo(obj){
    with(obj){
        a=2
    }
}
var o1={
    a:3
}

foo(o1)
console.log(o1);

从上面运行结果可以看出来,将o1()中a=3的值带入foo()函数中时,with修改了a的值,变成了2,这是修改o1()中有的变量。如果修改函数中没有的变量呢,输出结果会怎么样呢?看如下代码:

js 复制代码
function foo(obj){
    with(obj){
        a=2
    }
}

var o1={
    a:3
}

var o2={
    b:4
}

foo(o2)
console.log(a);

可以看出来,with修改foo(o2)中的a,但o2()函数中只有b=4,并没有a,所以此时修改的值a=2就会变为全局变量,当最后console.log(a)时,输出的结果就是全局变量a=2,这正是with()的用法。

相关推荐
CodeClimb6 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
光头程序员8 小时前
grid 布局react组件可以循数据自定义渲染某个数据 ,或插入某些数据在某个索引下
javascript·react.js·ecmascript
fmdpenny9 小时前
Vue3初学之商品的增,删,改功能
开发语言·javascript·vue.js
小美的打工日记9 小时前
ES6+新特性,var、let 和 const 的区别
前端·javascript·es6
涔溪9 小时前
有哪些常见的 Vue 错误?
前端·javascript·vue.js
程序猿online10 小时前
前端jquery 实现文本框输入出现自动补全提示功能
前端·javascript·jquery
Turtle12 小时前
SPA路由的实现原理
前端·javascript
HsuYang12 小时前
Vite源码学习(九)——DEV流程中的核心类(下)
前端·javascript·架构
傻小胖12 小时前
React 中hooks之useInsertionEffect用法总结
前端·javascript·react.js
蓝冰凌14 小时前
【整理】js逆向工程
javascript·js逆向