【JS高程设计学习笔记】第3章-语言基础

3.1 语法

3.1.1 区分大小写

ECMAScript中一切都区分大小写,无论是变量,函数名还是操作符。

3.1.2 标识符

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

字母,下划线,美元符号,数字。

其中数字不能用做第一个字符

驼峰命名法:第一个词首字母小写,后面的词首字母大写。例如 var firstSecond = function();

3.1.3 注释

单行注释://

多行注释:/*   */

3.1.4 严格模式

ES5增加的严格模式概念,ES3中的一些不规范写法会被处理,对不安全的活动将抛出错误,如果要对整个脚本执行严格模式,只需在脚本开头写上:

“use strict”;

所有现代浏览器都支持严格模式。

3.1.5 语句

ES语句以分号结尾,不加分号也有效,但是不推荐,因为当开发者删除空行压缩代码时,会容易导致语法错误。

多条语句可以合并到一个C语言风格的代码块中。{.....}

if等控制语句可以在执行单行语句是不使用代码块,但是最佳实践时始终在控制语句中使用代码块。

3.2 关键字与保留字

关键字有特殊用途,一般用来执行特殊的操作。ESMA-262 第六版 (ES6)所规定的关键字有非常多,具体的关键字可以在其他网站上查询。这些关键字不能用做标识符或者属性名。

规范中也描述了一组未来的保留字,不能做标识符,最好别做属性名。

3.3 变量

3.3.1 var 关键字

可以用来定义变量,来保存任意类型的值。

1. var 声明作用域

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

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

如果省略var 操作符,可以创建一个全局变量。这时可以在外部访问函数内的全局变量。

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

虽然可以省略var来创建全局变量,但是不推荐,因为很难维护。

也可以在一条var语句中定义多个变量,可以在一条语句中用逗号分隔每个变量。

2. var声明提升

所谓声明提升,就是把关键字声明的变量,自动提升到函数作用域顶部。

重点是会提升变量声明,但是不会赋值,这一点很关键。

3.3.2 let 声明

let的作用和var差不多但是区别非常大。最大的区别是,let声明的范围是块作用域,而var声明的范围是函数作用域。比如花括号内就是块作用域。块作用域是函数作用域的子集。举个直接栗子:

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

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

其次,let不允许同一个块中出现冗余声明,不然会报错。

1. 暂时性死区

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

2. 全局声明

与var不同,使用let在全局作用域中声明的变量不会成window对象的属性。

3. 条件声明

在用var声明变量的时候,由于声明会被提升,js引擎会自动将多余的声明在作用域顶部合并为一个声明。然而let不会受这个影响,不依赖条件声明模式。

4. for循环中的let声明

在let出现之前,for循环定义的迭代变量会渗透到循环体外部。主要是因为let是块作用域,可以把迭代变量限制在for循环体内部。

3.3.3 const 声明

const和let的行为基本相同,但是唯一一个重要的区别是,用const声明变量的时候必须同时初始化变量,且不能去尝试修改const声明的变量。

const也不允许重复声明,作用域也是块。

不能用const来迭代变量,因为会递增,所以不满足const不能修改的条件。

3.3.4 声明风格和最佳实践

作为ES6新增的两个关键字,let和const为js这门语言更精确的声明了作用域和语义。有助于提高代码质量的最佳实践如下:

1. 不使用var

2. const优先,其次是let

3.4 数据类型

ES有六种简单数据类型,也叫做原始类型:Undefined, Null, Boolean, Number, String, Symbol。其中Symbol是ES6新增。另外还有一种复杂的数据类型叫做Object对象。虽然很少,但是ES的数据类型很灵活,一个当多个用。

3.4.1 typeof 操作符

因为js的数据类型很松散,所以需要一个数据类型判断操作符,这就是typeof。typeof可以用来直接判断一个数据的类型:

  • undefined
  • boolean
  • string
  • number
  • object
  • function
  • symbol

值得一提的是,null的类型是object。

3.4.2 Undefined类型

Undefined类型只有一个值,undefined。一般在var和let声明变量但是没有赋值时,会出现这个特殊值。一般来说,永远不要显式的以undefined来初始化一个变量。

3.4.3 Null类型

Null类型也只有一个值,null。逻辑上来讲,null值表示一个空对象指针。

在定义将来要保存对象的一个变量是,建议使用null来初始化。

ECMA-262将null和undefined定义为表面上相等,即null == undefined。但是不全等。

3.4.4 Boolean类型

数据类型转换为true的值转换为false的值
Booleantruefalse
String非空字符串" "
Number非零数值(包括无穷)0,NaN
Object任意对象null
Undefined不存在undefined

3.4.5 Number类型

最基本的数值字面量格式是十进制。可以在数字前加一个0变为8进制,或者在前面加一个0x变为16进制。8进制在严格模式中是无效的。

1. 浮点值

定义浮点值,数值必须包含小数点,且后面必须至少有一个数字。

因为储存浮点数使用的内存空间是整数的两倍,所以ES会想方设法的把浮点数转化成整数,例如在小数点后面为0的情况。

对于非常大或者非常小的数,浮点值可以用科学计数法来表示。

let floatNum = 3.125e7; 等于 31250000

浮点值的精确值能最高达到17位小数,但是在计算中远不如整数精确。例如0.1 + 0.2不等于 0.3,之所以有这种错误,是因为使用了IEEE 754数值,因此永远不要测试某个特定的浮点值,这种情况并非ES独有。

2. 值的范围

最大数:Number.MAX_VALUE

最小数:Number.MIN_VALUE

3. NaN

特殊的数值,用于表示本来要返回数值的操作失败了,比如0和0相除。

注意如果非0整数和0相除,会得到正无穷或者负无穷,例如-5/0 = -infinity.

任何涉及NaN的运算都会返回NaN。

NaN不等于包括NaN在内的任何值。

IsNaN()可以用来测试一个值是否“不是数值”

4. 数值转换

Number(), parseInt(), parseFloat()

----Number ()

布尔值,true返回1,false返回0

数值,直接返回

null,返回0

undefined,返回NaN

字符串,若包含数值字符,则转换为一个十进制数,前缀有0则忽略掉;若包含有效的浮点值,则返回相应的浮点值;如果包含有效的十六进制格式,则会转换为十进制输出;如果是空字符串,则输出0;如果字符串包含除上述情况之外的其他字符,返回NaN。

对象,先调用valueOf()方法,并按照上述规则返回值,如果转换结果是NaN,则调用toString(),再按照字符串的规则转换。

----parseInt()

若是包含数值的字符串,返回数值;若是空字符串,返回NaN(与Number不同);若是浮点值,则抹除小数部分,返回整数部分;也可以把八进制和十六进制转换为十进制。

也可以通过传两个参数,扩展转换后获得的结果类型

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类似,不过能解析浮点数。需要注意的是,如果出现两个以上的小数点,只有第一个小数点会被解析。

3.4.6 String类型

1. 字符字面量

表示非打印字符或有其他用途的字符,用来转义。这些字符字面量可以出现在字符串中任意位置,且,可以作为单个字符被解释

2. 字符串的特点

ES中的字符串是不可变的,一旦创建,他们的值就不可变了。如果要修改某个变量中的字符串值,必须先销毁原始的字符串,然后将包含新值的另一个字符串保存到该变量,如:

let lang = "Java";
lang = lang + "Script";

3. 转换为字符串

有两种方式把一个值转换为字符串, num.toString() 和 String(num)

toString(),几乎所有值都有的方法,除了null和undefined。

多数情况下,toString不接受任何参数,但有一种情况会用到,就是把十进制的数转化为二进制,八进制,和十六进制。例如:

let num = 10;
console.log(num.toString(2)); // "1010"

String()转型函数,在不确认一个值是不是null和undefined的时候使用:

  • 如果值有toString()方法,则调用该方法返回结果
  • 如果值是null,返回"null"
  • 如果值是undefined,返回"undefined"

4. 模版字面量

ES6新增内容,利用反引号定义,与单双引号不同的是,模版字面量保留换行字符,可以跨行定义字符。所以模版字面量在定义模版是特别有用,比如HTML模版。

5. 字符串插值

模版字面量最常用的特性,可以在一个连续定义中插入一个或者多个值,一般插入多个值的时候,会比ES5时方便很多,下面是一个对比:

let value = 5;
let exponent = 'second';
let interpolatedString = 
    value + ' to the ' + exponent + ' power is ' + (value * value);
// 以前的实现方法
let interpolatedTemplateLiteral = 
    `${ value } to the ${ exponent } power is ${ value * value }`;
// 现在的实现方法
console.log(interpolatedString);             // 5 to the second power is 25
console.log(interpolatedTemplateLiteral);    // 5 to the second power is 25

6. 模版字面量标签函数(tag function)

支持定义标签函数,通过标签函数可以自定义插值行为。

7. 原始字符串

使用模版字面量也可以获取原始模版字面量内容,而不是转换后的字符表示,可以使用String.raw标签函数:

console.log(`\u00A9`); // ©️
console.log(`String.raw\u00A9`); // \u00A9

3.4.7 Symbol类型

ES6新增的数据类型,叫做符号symbol。符号是原始值,且符号实例是唯一,不可变的。符号的用途是确保对象属性使用唯一标识符,不会产生冲突的危险。

1. 符号的基本用法

符号需要用Symbol()函数初始化,但是Symbol()函数不能与new关键字一起用,符号没有字面量语法。可以给符号传入一个字符串参数,也叫description,但是与符号的定义与表示无关。

2. 使用全局符号注册表

如果运行时的不同部分需要共享和重用符号实例,那么可以用一个字符串作为key,在全局符号注册表中创建并重用符号。需要用到Symbol.for方法。

let foo = Symbol.for('foo');
let otherFoo = Symbol.for('foo');
console.log(foo == otherFoo); //true

如果不用Symbol.for,单纯用Symbol的话,上述两个符号是不相等的。

3. 使用符号作为属性

4. 常用内置符号

此部分内容属于进阶内容,这里不做过多讨论

3.4.8 Object 类型

开发者可以通过创建Object类型的实例来创建自己的对象,然后再给对象添加属性和方法。

每个Object实例有如下属性和方法:

  • constructor,用于创建当前对象的函数
  • hasOwnProperty(propertyName),用于判断当前对象实例(非原型)上是否存在给定的属性
  • isPrototypeof(object),用于判断当前对象是否为另一个对象的原型
  • propertyIsEnumerable(propertyName),用于判断给定的属性是否可以使用
  • toLocaleString(),返回对象的字符串表示,该字符串反映对象所在的本地化执行环境
  • toString() ,返回对象的字符串表
  • valueOf(),返回对象对应的字符串,数值或者布尔值表示。

3.5 操作符

3.5.1 一元操作符

1. 递增/递减操作符

i++ 先求值再加1

++i 先加1再求值

i--   先求值再减1

--i   先减1再求值

2. 一元加和减

3.5.2 位操作符

数值底层操作,ES中所有的数值都以IEEE 754 64位格式储存,但位操作不是直接应用到64位表示,而是先把值转换为32位整数,再进行位操作,之后再把结果转换为64位。开发者只能看到32位整数。

有符号整数使用32位的前31位表示整数值。第32位表示数值的符号,如0表示正,1表示负。这一位称为符号位(sign bit),它的值决定了数值其余部分的格式。

正值以真正的二进制格式存储,即31位中的每一位都以2的幂来表示,比如第一位表示2^0, 第二位表示2^1,以此类推。如18的二进制格式为10010。

而负值以二补数(或补码)的二进制编码存储。步骤如下:

  1. 确定绝对值的二进制表示
  2. 找到数值的一补数(或反码),换句话说,就是把0变成1,1变成0
  3. 给结果加1

1. 按位非

用波浪符~表示,它的作用是返回数值的一补数。按位非是为数不多的ES中的几个二进制数学操作符之一。按位非的最终效果是对数值取反并减1。栗子:

let num1 = 25;     //二进制00000000000000000000000000011001
let num2 = ~num1;  //二进制11111111111111111111111111100110
console.log(num2); //-26

虽然比起直接用负号给num1取反减一的结果相同,但是位操作符的速度要快很多。

2. 按位与

用&表示,有两个操作数,本质上,按位与就是将两个数的每一个位对其,然后基于真值表中的规则,对每一位执行相应的与操作。按位与操作在两个位都是1是返回1,在任何一位是0是返回0。

3. 按位或

用|表示,有两个操作数。在至少1位是1时返回1,两位都是0时返回0。

4. 按位异或

用^表示,有两个操作数,只在一位上是1的时候返回1,都是0或者都是1的时候返回0。

5. 左移

用<<表示,会按照指定的位数将数值的所有位向左移动,右端空出的位数用0填充。

6. 有符号右移

用>>表示,将数值所有位向右移动,同时保留符号。

7. 无符号右移

用>>>表示,对于正数,无符号右移与有符号结果相同。但是对于负数,区别会很大,有可能会变成正数。

3.5.3 布尔操作符

1. 逻辑非 !

2. 逻辑与 &&

3. 逻辑或 ||

3.5.4 乘性操作符

1. 乘法操作符 *

2. 除法操作符 /

3. 取模操作符 %

3.5.5 指数操作符

ES7新增,**,替代Math.pow()

3.5.6 加性操作符

1. 加法操作符

Infinity + -Infinity = NaN

-0 + +0 = +0

字符串:如果两个操作数都是字符串,将第二个字符串拼接到第一个字符串后面;如果只有一个操作数是字符串,则将另一个操作数转化为字符串,再将两个字符串拼接到一起。

2. 减法操作符

3.5.7 关系操作符

比较两个值,返回布尔值。<, >, <=, >=。

  • 如果操作数都是数值,比较数值
  • 如果操作数都是字符串,逐个比较比较对应字符的编码
  • 如果有任意一个操作数是数值,则将另一个操作数转换为数值之后再进行数值比较
  • 如果有任意一个操作数是对象,则调用其valueOf方法,取得结果后按前面的方式进行比较,如果没有该方法,则调用toString方法。
  • 如果有任意一个操作数是布尔值,则将其转换为数值再进行比较。

3.5.8 相等操作符

1. 等于和不等于

==, !=

2. 全等和不全等

===,!==

3.5.9 条件操作符

variable = boolean_expression ? true_value : false_value;

3.5.10 赋值操作符

*=, /=, %=, +=, -=, <<=, >>=, >>>=。使用这些只是为了简洁,不会提升性能。

3.5.11 逗号操作符

let num1 = 1, num2 = 2, num3 = 3;

3.6 语句

3.6.1 if 语句

if (condition){
    statement1;
} else {
    statement2;
}

3.6.2 do while 语句

do {
    statement
} while (expression)

3.6.3 while 语句

while (expression) {
    statement
}

3.6.4 for 语句

for (initialization; expression; post-loop expression){
    statement
}

3.6.5 for-in 语句

一种严格的迭代语句,用于枚举对象中的非符号键属性

for (property in expression) {
    statement
}

3.6.6 for-of 语句

一种严格的迭代语句,用于遍历可迭代对象的元素

for (property of expression) {
    statement
}

3.6.7 标签语句

可以后面通过break和continue引用,典型的应用场景是嵌套循环。

label: statement

3.6.8 break和continue语句

break立即退出循环,强制执行循环后的下一条语句

continue跳过当前循环,从循环头部再开始

3.6.9 with语句

将代码作用域设置为特定的对象,例如

// 对一个对象反复操作时
let qs = location.search.substring();
let hostName = location.hostname;
let url = location.href;

//如果用with,可以少写一些代码
with (location) {
    let qs = search.substring();
    let hoseName = hostname;
    let url = href;
}

3.6.10 switch语句

switch (expression) {
    case value1:
        statement
        break;
    case value2:
        statement
        break;
    case...
        ...    
        ...
    default:
        statement
}

3.7 函数

用来封装语句,可以在任何时间执行。下面是基本语法:

function functionName (arg1,arg2,...,argN) {
    statements
}

ES中的函数,不需要指定是否返回值,任何函数在任何时间,都可以通过return来返回值。不指定返回值的函数,实际上会返回undefined。

严格模式对函数的限制:

  • 函数不能以eval和arguments作为名称;
  • 函数的参数不能叫eval或arguments
  • 两个命名参数不能用同一个名称

若违反上述规则,则会导致语法错误,不执行代码。

总结

ES6+更新内容和其他可以重点关注的内容:

  • let和const的用法,以及区别
  • 新的原始数据类型,symbol,特点及常见用法
  • ES7新增指数操作符,替代Math.pow
  • 位操作符的理解
  • 数值,布尔值,字符串在进行不同运算或者比较时需要注意的点
  • for-in语句,for-of语句,和with语句的应用时机
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值