JavaScript高级程序设计(第4版)-第三章 语言基础学习笔记

1、语法

1.1区分大小写

ECMAScript 中一切都区分大小写

1.2 标识符

标识符:变量、函数、属性或者函数参数的名称。

  • 第一个字符必须是一个字母、下划线(_)或美元符号($);
  • 剩下的其他字符可以是字母、下划线、美元符号或数字。

按照惯例,使用驼峰大小写形式,eg. doSomethingImportant

1.3 注释
// 单行注释

/* 这是多行
注释 */ 
1.4 严格模式

对整个脚本启用严格模式:

  • 在脚本开头加上:“use strict”;

单独指定一个函数在严格模式下执行,将预处理指令放在函数体的开头:

function doSomething() { 
  "use strict"; 
  // 函数体 
} 
1.5 语句
  • 以分号为结尾,省略分号意味着由解析器确定语句在哪里结尾,加分号有助于防止省略造成的问题
  • 始终在控制语句中使用代码块,即使要执行的只有一条语句。代码块由一个左花括号({)标识开始,一个右花括号(})标识结束

2、关键字与保留字

ECMA-262 第 6 版规定的所有关键字如下:
在这里插入图片描述
以下是 ECMA-262 第 6 版为将来保留的所有词汇:
在这里插入图片描述
这些词汇不能用作标识符,但现在还可以用作对象的属性名。一般来说,最好还是不要使用关键字和保留字作为标识符和属性名,以确保兼容过去和未来的 ECMAScript 版本

3、变量

3.1 var 关键字
3.1.1 定义变量

var操作符+变量名(即标识符)

var message; 
3.1.2 定义变量并初始化
var message = "hi";

不初始化的情况下,变量会保存一个特殊值 undefined

3.1.3 定义多个变量并初始化

使用逗号分隔

var message = "hi", 
 found = false, 
 age = 29; 
3.1.4 var声明作用域

var 操作符定义的变量会成为包含它的函数的局部变量

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

使用 var在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁。

但是!
在函数内定义变量时省略 var 操作符,可以创建一个全局变量

function test() { 
 message = "hi"; // 全局变量
} 
test(); 
console.log(message); // "hi"

虽然可以通过省略 var 操作符定义全局变量,但不推荐这么做。

3.1.5 var声明提升

使用var关键字声明的变量会自动提升到函数作用域顶部,也就是把所有变量声明都拉到函数作用域的顶部。此外,反复多次使用 var 声明同一个变量也没有问题。
在这里插入图片描述

3.2 let关键字
3.2.1 let声明作用域

let 声明的范围是块作用域,而 var 声明的范围是函数作用域。

if (true) { 
 var name = 'Matt'; 
 console.log(name); // Matt 
} 
console.log(name); // Matt 

age 变量之所以不能在 if 块外部被引用,是因为它的作用域仅限于该块内部

if (true) { 
 let age = 26; 
 console.log(age); // 26 
} 
console.log(age); // ReferenceError: age 没有定义
3.2.2 let声明冗余

let 不允许同一个块作用域中出现冗余声明

var name; 
var name; 

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

JavaScript 引擎会记录用于变量声明的标识符及其所在的块作用域,因此嵌套使用相同的标识符不会报错,而这是因为同一个块中没有重复声明。

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 
3.2.3 暂时性死区

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

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

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

在 let 声明之前的执行瞬间被称为 “暂时性死区”(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出 ReferenceError。

3.2.4 全局声明

使用 let 在全局作用域中声明的变量不会成为 window 对象的属性(var 声明的变量则会)

var name = 'Matt'; 
console.log(window.name); // 'Matt' 

let age = 26; 
console.log(window.age); // undefined 

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

3.2.5 条件声明

没这么看懂其实

对于 let 这个新的 ES6 声明关键字,不能依赖条件声明模式

3.2.6 for循环中的let声明

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

在使用 var 的时候,最常见的问题就是对迭代变量的奇特声明和修改。之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的 i 都是同一个变量,因而输出的都是同一个最终值。

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

而在使用 let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。每个 setTimeout 引用的都是不同的变量实例,所以 console.log 输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。这种每次迭代声明一个独立变量实例的行为适用于所有风格的 for 循环,包括 for-in 和 for-of 循环

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

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

  • 声明时必须同时初始化
  • 不能修改其值
  • 不允许重复声明
  • 作用域是块
  • 不能使用const来声明迭代对象,比如for循环中,因为迭代变量会自增
  • 但可以用const声明一个不会被修改的for循环变量

const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制。

const person = {}; 
person.name = 'Matt'; // ok 
3.4 声明风格及最佳实践
  • 不使用var,限制自己只使用 let 和 const有助于提升代码质量,因为变量有了明确的作用域、声明位置,以及不变的值
  • const 优先,let 次之,使用 const 声明可以让浏览器运行时强制保持变量不变,应该优先使用 const 来声明变量,只在提前知道未来会有修改时,再使用 let

4、数据类型

6种简单数据类型

  • Undefined
  • Null
  • Boolean
  • Number
  • String
  • Symbol

1种复杂数据类型

  • Object
4.1 typeof操作符

作用:确定任意变量的数据类型

console.log(typeof 95);  // "number" 

对一个值使用 typeof 操作符会返回下列字符串之一:

  • "undefined"表示值未定义;
  • "boolean"表示值为布尔值;
  • "string"表示值为字符串;
  • "number"表示值为数值;
  • "object"表示值为对象(而不是函数)或 null;
  • "function"表示值为函数;
  • "symbol"表示值为符号。

调用typeof null 返回的是"object"。这是因为特殊值 null 被认为是一个对空对象的引用

4.2 Undefined类型

Undefined 类型只有一个值,就是特殊值 undefined。
当使用 var 或 let 声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值。所以不需要显示以undefined来初始化,因为默认情况下,任何未经初始化的变量都会取得undefined值

let message; 
console.log(message == undefined); // true 

无论是声明还是未声明,typeof 返回的都是字符串"undefined"。逻辑上讲这是对的,因为虽然严格来讲这两个变量存在根本性差异,但它们都无法执行实际操作。但是直接log输出未声明变量会报错

let message; // 这个变量被声明了,只是值为 undefined 
// 确保没有声明过这个变量
// let age 
console.log(typeof message); // "undefined" 
console.log(typeof age); // "undefined"

undefined 是一个假值。因此,如果需要,可以用更简洁的方式检测它。不过要记住,也有很多
其他可能的值同样是假值。所以一定要明确自己想检测的就是 undefined 这个字面值,而不仅仅是
假值

4.3 Null类型
  • Null 类型同样只有一个值,即特殊值 null。
  • 逻辑上讲,null 值表示一个空对象指针,这也是给typeof 传一个 null 会返回"object"的原因
  • 在定义将来要保存对象值的变量时,建议使用 null 来初始化,不要使用其他值。这样,只要检查这个变量的值是不是 null 就可以知道这个变量是否在后来被重新赋予了一个对象的引用。最好是显示初始化未保存的对象
  • undefined 值是由 null 值派生而来的,因此 ECMA-262 将它们定义为表面上相等
  • null 是一个假值
console.log(null == undefined); // true
4.4 Boolean类型
  • Boolean(布尔值)类型有两个字面值:true 和 false。这两个布尔值不同于数值,因此 true 不等于 1,false 不等于0
  • 布尔值字面量 true 和 false 是区分大小写的
  • 调用特定的 Boolean()转型函数,将其他类型的值转换为布尔值

不同类型与布尔值之间的转换规则
在这里插入图片描述
理解以上转换非常重要,因为像 if 等流控制语句会自动执行其他类型值到布尔值的转换,自动转换

4.5 Number类型
  • Number 类型使用 IEEE 754 格式表示整数和浮点值(在某些语言中也叫双精度值)
  • 十进制整数:最基本的数值字面量格式
  • 八进制:第一个数字必须是零(0),然后是相应的八进制数字(数值 0~7),在严格模式下无效—0o
  • 十六进制:值前缀 0x(区分大小写),然后是十六进制数字(0~9 以及 A~F)
4.5.1 浮点值
  • 要定义浮点值,数值中必须包含小数点,而且小数点后面必须至少有一个数字
  • 存储浮点值使用的内存空间是存储整数值的两倍
  • 在小数点后面没有数字的情况下,数值就会变成整数
  • 如果数值本身就是整数,只是小数点后面跟着 0(如 1.0),那它也会被转换为整数
  • 对于非常大或非常小的数值,浮点值可以用科学记数法来表示
4.5.2 值的范围
  • 最小值 Number.MIN_VALUE
  • 最大值 Number.MAX_VALUE

如果某个计算得到的数值结果超出了 JavaScript 可以表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity(无穷)值。如果计算返回正 Infinity 或负 Infinity,则该值将不能再进一步用于任何计算。

  • -Infinity(负无穷大)
  • Infinity(正无穷大)

确定一个值是不是有限大,使用 isFinite()函数
在计算非常大或非常小的数值时,有必要监测一下计算结果是否超出范围

4.5.3 NaN

NaN,意思是“不是数值”(Not a Number),用于表示本来要返回数值的操作失败了(而不是抛出错误)
在 ECMAScript 中,0、+0 或 -0 相除会返回 NaN

  • 任何涉及 NaN 的操作始终返回 NaN(如 NaN/10)
  • NaN 不等于包括 NaN 在内的任何值

isNaN()函数,接收一个参数,判断这个参数是否“不是数值”,任何不能转换为数值的值都会导致这个函数返回
true

console.log(isNaN(NaN)); // true 
console.log(isNaN(10)); // false,10 是数值
console.log(isNaN("10")); // false,可以转换为数值 10 
console.log(isNaN("blue")); // true,不可以转换为数值
console.log(isNaN(true)); // false,可以转换为数值 1
4.5.4 数值转换

将非数值转换为数值:Number()、parseInt() 和 parseFloat()

**Number()**是转型函数,可用于任何数据类型
在这里插入图片描述

let num1 = Number("Hello world!"); // NaN 
let num2 = Number(""); // 0 
let num3 = Number("000011"); // 11 
let num4 = Number(true); // 1 

parseInt()函数主要用于将字符串转换为数值
字符串最前面的空格会被忽略,从第一个非空格字符开始转换。
如果第一个字符不是数值字符、加号或减号,parseInt()立即返回 NaN。
如果第一个字符是数值字符、加号或减号,则继续依次检测每个字符,直到字符串末尾,或碰到非数值字符

let num1 = parseInt("1234blue"); // 1234 
let num2 = parseInt(""); // NaN 
let num3 = parseInt("0xA"); // 10,解释为十六进制整数
let num4 = parseInt(22.5); // 22 
let num5 = parseInt("70"); // 70,解释为十进制值
let num6 = parseInt("0xf"); // 15,解释为十六进制整数

parseInt()也接收第二个参数,用于指定底数(进制数),多数情况下解析的应该都是十进制数,此时第二个参数就要传入 10,建议始终传给它第二个参数。

let num1 = parseInt("10", 2); // 2,按二进制解析
let num2 = parseInt("10", 8); // 8,按八进制解析
let num3 = parseInt("10", 10); // 10,按十进制解析
let num4 = parseInt("10", 16); // 16,按十六进制解析

parseFloat()函数主要用于将字符串转换为数值
工作方式跟 parseInt()函数类似,都是从位置 0 开始检测每个字符。同样,它也是解析到字符串末尾或者解析到一个无效的浮点数值字符为止。这意味着第一次出现的小数点是有效的,但第二次出现的小数点就无效了,此时字符串的剩余字符都会被忽略。
它始终忽略字符串开头的零
parseFloat()只解析十进制值,因此不能指定底数

let num1 = parseFloat("1234blue"); // 1234,按整数解析
let num2 = parseFloat("0xA"); // 0 
let num3 = parseFloat("22.5"); // 22.5 
let num4 = parseFloat("22.34.5"); // 22.34 
let num5 = parseFloat("0908.5"); // 908.5 
let num6 = parseFloat("3.125e7"); // 31250000 
4.6 String 类型

String(字符串)数据类型表示零或多个 16 位 Unicode 字符序列。
字符串可以使用双引号(")、单引号(’)或反引号(`)标示。
以某种引号作为字符串开头,必须仍然以该种引号作为字符串结尾。

4.7 Symbol类型
4.8 Object类型

5、操作符

6、语句

7、函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值