000001 - JavaScript语言基础(一)

文章介绍了JavaScript的基本语法,包括区分大小写、标识符规则和注释方式。重点讲解了变量的声明,如var、let和const的区别,特别是let带来的块级作用域和变量提升的概念。还提到了保留字和关键字的使用限制。
摘要由CSDN通过智能技术生成

000001 - JavaScript语言基础(一)

1、语法
1.1区分大小写

无论是变量、函数名还是操作符,都区分大小写。变量test和变量Test是两个不同的变量

1.2标识符

所谓标识符,就是变量、函数、属性或函数参数的名称。边师傅可以由一或多个下列字符组成:

  • 第一个字符必须是一个字母、下划线或美元符号
  • 剩下的其他字符可以是字母、下划线、美元符号或数字
1.3注释
// 单行注释
/* 这是多行
注释 */
1.4语句

以分号结尾,省略分号意味着由解析器确定语句在哪里结尾

let sum = a + b  // 没有分号也有效,不推荐
let diff = a - b; // 加分号有效,推荐

多条语句可以合并到一个C语言风格的代码块中。代码块由一个左花括 号({)标识开始,一个右花括号(})标识结束:

if (test) {
    test = false; console.log(test);
}

在控制语句中使用代码块可以让内容更清晰,在需要修改代码时也可以 减少出错的可能性

2、关键字与保留字

保留的关键字不能用作标识符或属性名

break     do       in           typeof
case      else     instanceof   var
catch     export   new          void
class     extends  return       while
const     finally  super        with
continue  for      switch       yield
debugger  function this        default
if        throw    delete      import
try

规范中也描述了一组未来的保留字,同样不能用作标识符或属性名。虽然保留字在语言中没有特定用途,但它们是保留给将来做关键字用的

始终保留: 
enum
严格模式下保留:
implements package
public interface
protected static
let private
模块代码中保留:
await

这些词汇不能用作标识符,但现在还可以用作对象的属性名。一般来说,最好还是不要使用关键字和保留字作为标识符和属性名

3、变量

变量可以用于保存任何类型的数据。每个变量只不过是一个用于保存任意值的命名占位符。有3个关键字可以声明变量:var、const和let。

3.1 var关键字
var message; // 定义变量	
var message = 'hi'; // 定义变量的同时并设置它的值

变量message首先被定义为一个保存字符串值hi的变 量,然后又被重写为保存了数值100。虽然不推荐改变变量保存值的类型,但这在ECMAScript中是完全有效的。

var message = "hi";
message = 100; // 合法,但不推荐
01. var声明作用域

使用var操作符定义的变量会成为包含它的函数 的局部变量。比如,使用var在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁:

function test() {
    var message = "hi"; // 局部变量
}test();
console.log(message); // 出错!

message变量是在函数内部使用var定义的。函数叫test(), 调用它会创建这个变量并给它赋值。调用之后变量随即被销毁,因 此示例中的最后一行会导致错误。不过,在函数内定义变量时省 略var操作符,可以创建一个全局变量:去掉之前的var操作符之后,message就变成了全局变量。只要调用 一次函数test(),就会定义这个变量,并且可以在函数外部访问到

function test() {
    message = "hi"; // 全局变量
}
test();
console.log(message); // "hi"
02. var声明提升

使用var时,下面的代码不会报错。这是因为使用这个关键字声明 的变量会自动提升到函数作用域顶部

function foo() {
    console.log(age);
    var age = 26;
}foo(); // undefined

之所以不会报错,是因为ECMAScript运行时把它看成等价于如下代码:

function foo() {
    var age;
    console.log(age);
    age = 26;
}foo(); // undefined

反复多次使用var声明同一个变量也没有问题:

function foo() {
    var age = 16;
    var age = 26;
    var age = 36;
    console.log(age);
}foo(); // 36
3.2 let声明

let跟var的作用差不多,但有着非常重要的区别。最明显的区别是,let声明的范围是块作用域,而var声明的范围是函数作用域:

if (true) {
    var name = 'Matt';
    console.log(name); // Matt
}
console.log(name); // Matt
if (true) {
    let age = 26;
    console.log(age); // 26
}
console.log(age); // ReferenceError: age没有定义

在这里,age变量之所以不能在if块外部被引用,是因为它的作用域仅 限于该块内部。块作用域是函数作用域的子集,因此适用于var的作用 域限制同样也适用于let。

let也不允许同一个块作用域中出现冗余声明。这样会导致报错:

var name;
var name;
let age;
let age; // SyntaxError;标识符age已经声明过了

嵌套使用相同的标识符不会报错,而这是因为同一个块中没有重复声明:

var name = 'Nicholas';
console.log(name); // 'Nicholas'
if (true) {
    var name = 'Matt';
    console.log(name); // 'Matt'
}
let age = 30;
console.log(age); // 30
if (true) {
    let age = 26;
    console.log(age); // 26
}

对声明冗余报错不会因混用let和var而受影响。这两个关键字声明的并不是不同类型的变量,它们只是指出变量在相关作用域如何存在。

var name;
let name; // SyntaxError
let age;
var age; // SyntaxError
01. 暂时性死区

let与var的另一个重要的区别,就是let声明的变量不会在作用域中被提升。

// name会被提升
console.log(name); // undefined
var name = 'Matt';

// age不会被提升
console.log(age); // ReferenceError:age没有定义
let age = 26;
02. 全局变量

与var关键字不同,使用let在全局作用域中声明的变量不会成为window对象的属性(var声明的变量则会)。

var name = 'Matt';
console.log(window.name); // 'Matt'
let age = 26;
console.log(window.age); // undefined

不过,let声明仍然是在全局作用域中发生的,相应变量会在页面的生命周期内存续。因此,为了避免SyntaxError,必须确保页面不会重复声明同一个变量。

03. 条件声明

在使用var声明变量时,由于声明会被提升,JavaScript引擎会自动 将多余的声明在作用域顶部合并为一个声明。因为let的作用域是块,所以不可能检查前面是否已经使用let声明过同名变量,同时也就不可能在没有声明的情况下声明它。

<script>
    var name = 'Nicholas';
    let age = 26;
</script>
<script>
    // 假设脚本不确定页面中是否已经声明了同名变量
    // 那它可以假设还没有声明过
    var name = 'Matt';
    // 这里没问题,因为可以被作为一个提升声明来处理
    // 不需要检查之前是否声明过同名变量
    let age = 36;
    // 如果age之前声明过,这里会报错
</script>
04. for循环中的let声明

在let出现之前,for循环定义的迭代变量会渗透到循环体外部,改成使用let之后,这个问题就消失了,因为迭代变量的作用域仅 限于for循环块内部:

for (var i = 0; i < 5; ++i) {
    // 循环逻辑
}
console.log(i); // 5

for (let i = 0; i < 5; ++i) {
    // 循环逻辑
}console.log(i);  // ReferenceError:i没有定义

在使用var的时候,最常见的问题就是对迭代变量的奇特声明和修改,而在使用let声明迭代变量时,JavaScript引擎在后台会为每个迭代 循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变 量实例,所以console.log输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。

for (var i = 0; i < 5; ++i) {
    setTimeout(() => console.log(i), 0)
}
// 你可能以为会输出0、1、2、3、4
// 实际上会输出5、5、5、5、5


for (let i = 0; i < 5; ++i) {
    setTimeout(() => console.log(i), 0)
}
// 会输出0、1、2、3、4
3.3const声明

const的行为与let基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改const声明的变量会导致运行时错误。

const age = 26;
age = 36; // TypeError: 给常量赋值
// const也不允许重复声明
const name = 'Matt';
const name = 'Nicholas'; // SyntaxError
// const声明的作用域也是块
const name = 'Matt';
if (true) {
    const name = 'Nicholas';
}
console.log(name); // Matt

如果const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反const 的限制。

const person = {};
person.name = 'Matt'; // ok

如果你只想用const声明一个不会被修改的for循环变量,那也是 可以的。也就是说,每次迭代只是创建一个新变量。这对for-of和for- in循环特别有意义。

let i = 0;
for (const j = 7; i < 5; ++i) {
    console.log(j);
}// 7, 7, 7, 7, 7
for (const key in {a: 1, b: 2}) {
    console.log(key);
}
// a, b
for (const value of [1,2,3,4,5]) {
    console.log(value);
}// 1, 2, 3, 4, 5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值