一、 前言
由于工作繁忙,也是自己比较懒。 更新也是断断续续的。 素材大多来自于工作,有很大的局限性。后续想多找点实战来分析分析。写好久了,文章水平也是一点长进没有。所以决定做一个【JS基础系列】出来。一是为了提高自己的文章水平。二是难度不高,【JS基础系列】断更的概率不大。三也是给自己的定位从来都不是什么大牛。
暂定的是每周更新一期,从JS最基础【变量与作用域】到【异步编程,密码学与混淆】。计划历时6个月左右。希望自己能坚持下来, 也希望给准备入行JS逆向的朋友一些帮助
二、本节涉及知识点
1- 变量
2- 作用域
三、重点内容
1- 变量的概念:
首先,变量大家都懂。我们可以理解为存储数据的容器。 我们给这个容器一个名字,之后就可以通过这个名字去提取容器中的内容。
2、变量声明:
JS中变量的声明有三种方法: var、let、 const
1)const:
const是ES6中引入的【这里有两个点, 不清楚的同学可以查看详情,JavaScript引擎1和ES62规范】, 通常用于声明常量。
const通常用于声明常量,因为其特性为不能重复定义且无法修改变量值。【constant :常理】
const PI = 3.14159;
console.log(PI); // 3.14159
PI = 3; // 报错:Uncaught TypeError: Assignment to constant variable.
但是如果我们定义对象, 可以修改对象属性,达到修改值的目的
const person = { name: "John", age: 30 };
person = { name: "Jane", age: 25 }; // 报错:Uncaught TypeError: Assignment to constant variable.person.age = 31; // 可以修改对象的属性
console.log(person); // { name: "John", age: 31 }
同样的效果在数组中也可以实现
const numbers = [1, 2, 3];
numbers[0] = 100; // 可以修改数组的元素
console.log(numbers); // [100, 2, 3]numbers = [4, 5, 6]; // 报错:Uncaught TypeError: Assignment to constant variable.
2)let:
let 的基本定义:
let 是在 ES6 引入的一个关键字,用于声明块级作用域(block-scoped)的变量。
let 只在其声明所在的 块级作用域 内有效。块级作用域指的是由 {} 包裹的代码块(例如函数、if 语句、for 循环等)。
这里说的,只在块级作用域生效并不是指,let不可以在全局作用域中使用。 而是,let声明的变量不会挂载到window上。只能在哪个区域声明,哪个区域使用。
let c = 30;
console.log(c); // 输出: 30
console.log(window.c); // undefined
3)var:
var 的作用域:
var 声明的变量具有 函数作用域,也就是说,使用 var 声明的变量只在它所在的函数内部有效。如果 var 声明在函数外部(即全局作用域),则该变量在整个脚本中都有效。
这里需要注意的是。var声明只在函数内部有效,是指。 var无法识别块级作用域,如果在函数内部使用var声明了变量,则该变量会提升到函数顶部。而不管是否在函数作用域中的块级作用域中。
function test() {var a = 10;console.log(a); // 输出: 10
}
console.log(a); // ReferenceError: a is not defined
3、作用域:
1)作用域的概念:
我们上面提到了这么多次作用域, 可能有同学会问,作用域是什么:
作用域(Scope) 是指程序中可以访问和修改某个变量的区域或范围。在 JavaScript 中,作用域决定了变量、函数和对象的可访问性及其生命周期。不同的作用域类型控制着代码块内变量的作用范围。
作用域分: 全局作用域, 函数作用域 和 块作用域
2)全局作用域(Global Scope)
变量或函数在整个程序中都可以访问和修改的范围。
在全局作用域中声明的变量是全局变量,可以在任何地方访问。
在浏览器中,所有在全局作用域中声明的变量都会成为 window 对象的属性。
我们最直观的判断就是, window上挂在的变量或者对象,就是全局变量或全局对象
var globalVar = "I'm a global variable";function test() {console.log(globalVar); // 可以访问全局变量
}test(); // 输出: "I'm a global variable"
3)函数作用域(Function Scope)
变量在函数内部声明时,作用域仅限于该函数内部,外部无法访问。
函数作用域是 JavaScript 在 var 声明变量时默认使用的作用域。
function myFunction() {var localVar = "I'm a local variable";console.log(localVar); // 可以访问
}myFunction();
console.log(localVar); // ReferenceError: localVar is not defined
4)块级作用域(Block Scope)
只有在 {} 代码块中声明的变量,才会受到块级作用域的限制。
let 和 const 引入了块级作用域,使得它们只在 {} 代码块内有效。
例如,在 if、for、while 语句中的声明会只在该语句块内部有效。
只有let和const定义的变量会识别到块级作用域
if (true) {let blockVar = "I'm inside a block";console.log(blockVar); // 可以访问
}
console.log(blockVar); // ReferenceError: blockVar is not defined
5)作用域链(Scope Chain)
当你访问一个变量时,JavaScript 引擎会沿着 作用域链 向外查找,直到找到该变量为止。作用域链的顺序是从当前作用域开始,然后逐层向外查找,直到全局作用域。
var globalVar = "I'm a global variable";function outerFunction() {var outerVar = "I'm an outer variable";function innerFunction() {var innerVar = "I'm an inner variable";console.log(innerVar); // 访问内层作用域的变量console.log(outerVar); // 访问外层作用域的变量console.log(globalVar); // 访问全局作用域的变量}innerFunction();
}outerFunction();
作用域链 从 innerFunction 开始,查找 innerVar,然后查找 outerVar,最后查找 globalVar。
6)作用域与变量提升
在 JavaScript 中,变量的声明会被提升到作用域的顶部,但是赋值不会被提升。对于不同作用域中的变量,它们会分别提升到各自作用域的顶部。
function example() {console.log(a); // undefined,因为变量声明被提升了,但是赋值没有var a = 10;
}example();
在函数作用域中,var a 会被提升到函数的顶部,但在它赋值之前,a 的值是 undefined。
四、 总结
了解知识点: JavaScript引擎、 ES6规范、变量、作用域、作用域链
我们在学习其他语言时,都知道每种语言都有它自己的解释器。 而JavaScript的解释器就是我们这里说的JavaScript引擎。
JavaScript引擎主的工作原理一般为三步:
1- 解析(Parsing): 首先JavaScript引擎先读取JavaScript 代码将其转化为一种抽象语法树(AST, Abstract Syntax Tree)的结构.AST 是代码的树形表示,每个节点代表一个语法结构,如变量、运算符、函数等。
2- 编译(Compilation): 大部分现代 JavaScript 引擎使用即时编译(JIT,Just-In-Time Compilation)。在这一阶段,引擎将 JavaScript 代码从源代码或 AST 转换为中间表示(如字节码),并在执行过程中将这些字节码编译为机器代码。编译过程是动态的,根据程序的执行情况优化代码。
3- 执行(Execution): 执行阶段是 JavaScript 引擎真正运行代码的部分,它使用 JIT 编译器生成的机器代码来执行任务。JavaScript 引擎通过栈、堆等数据结构管理内存和执行上下文,并且遵循 JavaScript 的单线程异步执行模型。
JavaScript引擎大概有以下几种:
1、 V8:由 Google 开发,主要用于 Chrome 浏览器。【我们逆向期间最常使用的】
2、 SpiderMonkey:由 Mozilla 开发,主要用于 Firefox 浏览器。
3、 JavaScriptCore(也叫 Nitro):由 Apple 开发,主要用于 Safari 浏览器。
4、 Chakra:由 Microsoft 开发,曾用于旧版的 Edge 浏览器。
总结:JavaScript引擎, 先将js代码解析为AST语法数。 并对js代码进行一些基本准备操作。 如:变量提升、暂时性死区、执行上下文、作用域等。随后AST语法树被转成机器代码,并被执行。 ↩︎ES6规范:ES6(全称:ECMAScript 2015)是 ECMAScript 标准的第六个版本,通常也被称为 ES6 或 ES2015。ECMAScript 是 JavaScript 的规范标准,所有现代 JavaScript 引擎(如 V8、SpiderMonkey 等)都遵循这一标准。我们可以简单的理解为:为了统一JS语法,让各个JS引擎都能支持而出的一种规范【当然ES6也做了一些性能上的提升,不完全只是统一规范】。 ↩︎