第3章 基本概念
# 第3章 基本概念
# 3.1 语法
# 3.1.1 标识符、注释
所谓标识符,就是指变量、函数、属性的名字,或者函数的参数,采用驼峰格式,第一个字母小写,剩下的每个单词的首字母大写,例如:
firstSecond
myCar
doSomethingImportant
ECMASCript使用C风格的注释,包括单行注释和块级注释
// 单行注释
/*
* 多行注释
*/
# 3.2 关键字和保留字
关键字是具有特定用途的,比如控制语句或其他特定操作,关键字、保留字、true
、false
和null
不能用作标识符:
关键字 | 关键字 | 关键字 | 关键字 |
---|---|---|---|
break | do | instanceof | typeof |
case | else | new | var |
catch | finally | return | void |
continue | for | switch | whitle |
debugger | function | this | with |
default | if | throw | |
delete | in | try |
保留字是将来可能有特定用途,但现在还没规定特定用途的。ES3定义的全部保留字:
保留字 | 保留字 | 保留字 | 保留字 |
---|---|---|---|
abstract | enum | int | short |
boolean | export | interfact | static |
byte | extends | long | super |
char | final | native | synchronized |
class | float | package | throws |
debugger | implements | protected | volatile |
double | import | public | let |
# 3.3 变量
变量:可变的量,在编程语言中,变量其实就是一个名字,用来存储和代表不同值的东西。
用var操作符定义的碧昂量将成为定义该变量的作用域中的局部变量,如果在函数中使用var定义一个变量,那么这个变量在函数执行后就会被销毁。
声明变量有以下几种方式:
// ES3
var a = 123;
// ES6
let b = 100;
b = 200 //报错
const c = 1000;
// 创建函数也相当于在创建变量
function fn() {}
// 创建类也相当于创建变量
class A{}
// ES6的模块岛屿也可以创建变量
import a from './a.js'
// Symbol创建唯一值
let n = Symbol(100)
let m = Symbol(100)
总结:
- 用
var
声明的变量,可以重复声明,后声明的会覆盖前面的 - 用
let
声明的变量具有作用域,在同一作用域下不可重复声明变量,但是可以修改变量的值,例如let a = 1;
,不能再次声明a
,let a = 2;
会报错,提示:Uncaught SyntaxError: Identifier 'a' has already been declared
- 用
const
声明的变量为常量,不能修改该变量的值,但是像Object
这样的复杂数据类型,在内存中存放的是一个指向该对象的指针,也就是说,用const
声明的对象仍然可以修改该对象的值,但不可再次声明该对象
# 3.4 数据类型
ESMAScript中数据分为两大类:一是基本数据类型:Undefined
、Null
、Boolean
、Number
、String
、Symbol
,二是复杂数据类型:Object
,Object
本质上是由一组无序的名子对组成的。
基本数据类型
数字
Number
(常规数字和NaN
)字符串
String
布尔值
Boolean
空指针
Null
未定义
Undefined
唯一值(独一无二的值)
Symbol
引用数据类型
Object
对象类型{}
普通对象[]
数组对象RegExp
正则对象Function
函数数据类型Math
数学函数对象Date
日期对象
数据类型应用场景:
当我们通过Ajax
请求拿到数据之前,先在本地初始化数据,一般都会先给一个默认的数据,请求数据后再把数据放入到我们定义好的数据结构里面,比如:
var data = {
count: 0,
isActive: true,
goods: [],
model: null,
message: ''
}
# 3.4.1 typeof操作符
typeof
操作符用于检测给定变量的数据类型。typeof
操作符可以检测的数据类型有:
undefined
boolean
string
number
object
function
var message = 'some string'
console.log(typeof(message) // "string"
var arr = [1,2,3,4]
console.log(typeof(arr) // "object"
console.log(typeof(null) // "object"
在上面的例子中调用 typeof null
会返回"object"
,因为特殊值null
被认为是一个空的对象引用。用typeof
检测一个变量是否是数组并不准确,会返回"object"
,使用Object.prototype.toString()检测数据类型更加准确
# 3.4.2 Undefined类型和Null类型
undefined类型只有一个值,即特殊的undefined,一个变量声明了但未赋值,默认是undefined
var message;
console.log(message == undefined) // true
undefined
和null
区别:
null
和undefined
都代表的是没有。
null
是意料之中:一般都是开始不知道值,我们手动先设置为null
,后期再给予赋值操作,例如,let num = null
,一般最好用null
作为初始的空值,因为0
值不是空值,它在栈内存中有自己的存储空间(占了位置)
undefined
是意料之外:不是我们能决定的,创建一个变量没有赋值,默认是undefined
let num = null;
null = 12;
# 3.4.3 Boolean类型
只有两个字面值;true和false,这两个值与数字值不是一回事,因此true不一定等于1,而false也不一定等于0。
只有0
、NaN
、''
、null
、undefined
五个值转换为false
,其余都转换为true
(而且没有任何的特殊情况)
数据类型 | 转换为true的值 | 转换为false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | ""空字符串 |
Number | 任何非零数字值(包括无穷大) | 0 和 NaN |
Object | 任何对象 | null |
Undefined | 不适用 | undefined |
Boolean(true) // true
Boolean(false) // false
Boolean('Hello Wolrd') // true
Boolean() // false
Boolean('') // false
Boolean(' ') // true (里面有空格)
Boolean(1) // true
Boolean(0) // false
Boolean(NaN) // false
Boolean({}) // true
Boolean([]) // true
Boolean(null) // false
Boolean(undefined) // false
把其他类型转换为布尔类型有三种方式:
Boolean()
!
或!!
取反:先转为布尔,然后取反- 条件判断
# 3.4.4 Number类型
Number类型使用IEEE754格式来表示整数和浮点值,这也是0.2 + 0.3
不等于0.5
的原因,
最基本的数值类型字面量格式是十进制整数
var a = 10;
# 1. 浮点数值
整理中。。。
# 2. NaN
Not a Number
:不是一个数,但它属于数值类型
NaN的特点
- NaN和任何值进行操作都会返回NaN
- NaN与任何值都不相等,包括NaN本身
console.log(NaN == NaN)
# 3. isNaN函数
用于检测一个变量不是数值(Number
)类型。isNaN()
接收一个参数,这个参数可以是任何类型。这个函数会尝试把传入的参数转换为数值,某些不是数值的值会直接转换成数值,例如字符串"10"
或Boolean
值,不能转换为数值的值返回true
,能转换的返回false
。
console.log( isNaN(NaN ) // true
console.log( isNaN(10 ) // false
console.log( isNaN('10') // false
console.log( isNaN('blue') // true
console.log(isNaN( true )) // false (true会被转换成1)
总结:
isNaN
意思是:是不是非数值
,是的话返回true
,所有能被该函数转换能Number
类型的值,都返回false
。- 在使用isNaN进行检测的时候,首先会验证检测的值是否为数字类型,如果不是,先基于Number()这个方法,把值转换成数字类型,然后再检测。
- 空字符串、空数组、布尔值、
null
会转成数值,所以isNaN
函数返回false
。 - 空对象、函数、
undefined
不能转换成数值,返回true
。
# 4. 数值转换
把非数值值转换为数值:
Number()
parseInt()
取整parseFloat()
浮点数
`Number()转换规则
- 如果是布尔值,
true
和false
会被转换为1
和0
。
Number(true) // 1
Number(false) // 0
- 如果是数字,只是简单的传入和返回。
Number(1) // 1
Number(100) // 100
- 如果是
null
值,返回0
。
Number(null) // 0
- 如果是
undefined
,返回NaN
。
Number(undefined) // NaN
- 如果是字符串:
- 字符串中只包含数字(包括前面带正/负号的情况),则将其转换为十进制数值,数字前面有
0
的会被忽略(不管前面有几个0
,全部忽略),例如"010"
会转换成10
。 - 字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值。
- 字符串中包含有效的十六进制格式(一般用数字
0
到9
和字母A
到F
(或a~f
)表示,其中:A~F
表示10~15
,这些称作十六进制数字),如"0xf",
将其转换成相同大小的十进制整数值。 - 字符串为空,转换成
0
。 - 字符串中包含除了以上格式之外的字符,则转换为NaN,如字符串中既有数字又有字母的情况。
- 字符串中只包含数字(包括前面带正/负号的情况),则将其转换为十进制数值,数字前面有
// 规则一
Number("1") // 1
Number("123") // 123
Number("010") // 10 (前导的0会被忽略)
Number("-10") // -10
// 规则2
Number("1.1") // 1.1
Number("0.1") // 0.1
Number("0000.1") // 0.1 (前导的0会被忽略)
// 规则3
Number(0xf) // 15
// 规则4
Number("") // 0
Number(" ") // 0
Number('') // 0
// 规则5
Number("Hello Wolrd") // NaN
Number("0ff6600") // NaN
Number("ff6600") // NaN
Number("0.1a") // NaN
Number("10a") // NaN
Number("a10.1") // NaN
var goodsList = {
'pop':
}
var arr = [1,2,3,4]
Number(arr)
- 如果数组或对象,返回
NaN
(估计没有人会这么傻,用Number()
函数去转换吧...)。
# parseInt(string,radix)
将一个字符串转换成x进制的整数。
传入的第一个参数为字符串,如果参数不是字符串,则将其转换为字符串(使用 ToString
抽象操作)。字符串开头的空白符将会被忽略。
第二个参数为整数,表示按照xx
进制转换,如传入参数10
表示按十进制规则转换,
从左到右依次查找有效数字字符,直到遇到非有效数字字符,停止查找(不管后面是否好友数字),把找到的当做数字返回。
如果字符串中以0x
开头且后跟数字字符,就会将其当做一个十六进制整数。
如果字符串以"0"
开头且后跟数字字符,则会被当做一个八进制数来解析。
如果不传第二个参数,会按照八进制解析。在大多数情况下,我们要解析的都是十进制数值,因此始终将10作为第二个参数是非常必要的。
parseInt("123abc") // 123
parseInt("") // NaN
parseInt("12.5px") // 12
parseInt("0xA") // 10 (16进制)
parseInt("0xf") // 15 (16进制)
parseInt("070") // 70
parseInt("70") // 70
# parseFloat(string)
解析一个参数(必要时先转换为字符串)并返回一个浮点数。默认解析十进制值。
function circumference(r) {
return parseFloat(r) * 2.0 * Math.PI;
}
console.log(circumference(4.567));
// expected output: 28.695307297889173
console.log(circumference('4.567abcdefgh'));
// expected output: 28.695307297889173
从左到右依次解析字符,一直解析到字符串末尾,遇到非数字字符会或遇到第二个浮点数(在这之前的字符串都会被解析)会使解析停止,如
"3.14"
解析成3.14
,"3.14.1234"
解析成3.14
忽略参数首尾空白符
parseFloat("3.14") // 3.14
parseFloat("-3.14") //-3.14
parseFloat("+3.14") //3.14
parseFloat("0003.14") // 3.14
parseFloat(" 3.14 ") // 3.14
parseFloat("3.14abc") // 3.14
parseFloat("3.14.5678") // 3.14
parseFloat("abc3.14") // NaN
parseFloat("abc123") // NaN
parseFloat("123abc") // 123
总结:
为什么Number
和parseInt/parseFloat
计算结果不一样呢?
Number
转换规则是浏览器底层渲染规则,是浏览器的一个非常重要的方法,parseInt/parseFloat
是一个单独方法的规则,就是用来处理字符串的。Number
走的是整个V8
引擎最底层的机制,遇到其他类型,底层机制会告诉我们哪个类型跟哪个类型应该怎么转换,这是底层机制已经规定好的,比如遇到布尔值,true
转为1
,false
转为0
parseInt
和parseFloat
是额外提供的方法,就是浏览器提供的方法,它们的源码处理机制很简单,会先把传入的参数转换为字符串,然后在从左到右查找数字有效字符。
let a = 12;
a>=0&& a<=20?(a%2===0?a+=2:null):a-=2 //a => 14
let a = 12;
if(a>=2&&a<=20) {
if(a%2 === 0) {
a+=2;
}
} else {
a-=2;
}
console.log(a)
# 3.4.5 String类型
所有用单引号、双引号、反引号包起来的都是字符串。
# 把其他类型值转换为字符串
- [val].toString()
- 字符串拼接
var age =18;
var ageAsString = age.toString() // "11"
let a = 10 + null + true + [] + undefined + 'Hello' + null + [] + 10 + false;
console.log(a) // 11undefinedHellonull10false
console.log(let a = 10 + null + true + [] + undefined + 'Hello' + null + [] + 10 + false;
console.log(10 + null + true + [] + undefined + 'Hello' + null + [] + 10 + false)
let str = 'Hello World'
案例解析:
- 第一步,
10 + null => 10
null转换成数值为0, 10 + 0 = 10。 - 第二步,
10 + true => 11
true转为为数值为1,10 + 1 = 11 - 第三步,
11 + [] => "11"
[]转换为字符串为空,数值和遇到字符串+号变为连接符11 + "" = "11" - 第四步,
"11" + undefined
=> "11undefined" 字符串后使用+号,当做连接符,后面的也一样 - 所有最终结果为 11undefinedHellonull10false
# 3.4.6 Object类型
ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过执行new操作符狗跟需要创建的对象类型名称来创建。对象实例拥有属性property和方法method
// 声明方式1
var obj = new Object()
// 声明方式2
var obj = {}
每个Object实例都拥有下列属性和方法:
- constructor:保存用于创建当前对象的函数。
- hasOwnProperty(propertyName):用于检查给定属性在当前对象实例中是否存在。
- isPortotypeOf(object):传入对象是否是另一个对象的原型。
- propertyIsEnumberable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。
- toLocaleString():返回对象的字符串表示。该字符串与执行环境的地区对应。
- toString():返回对象的字符串表示。
- valueOf():返回对象的字符串、数值或者布尔值表示。通常与toString()方法的返回值相同。
# 3.5 操作符
# 3.5.1一元操作符
# 1. 递增和递减操作符
# 2. 一元加和减操作符
# 3.5.2 位操作符
# 3.5.3 布尔操作符
# 1.逻辑非 !
# 2. 逻辑与 &&
逻辑与操作,有两个操作数(条件)
var result = true && false;
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | false | false |
fasle | true | false |
false | false | false |
# 3.
# 3.6 语句
# 3.7 函数
# 3.8 小结
JavaScript的核心语言特性在ECMA-262中以名为ECMAScript的伪语言的形式来定义的。ECMAScript中包含了所有基本的语法、操作符、数据类型以及完成基本的计算任务说必须的对象,但没有对取得输入和产生输出的机制做出规定。理解ECMAScript以及其复杂的各种细节,是理解其在Web浏览器中的实现——JavaScript的关键。下面总结了ECMAScript中基本的要素。
- ECMAScript中的基恩数据类型包括Undefined、Null、String、Number、Boolean和Symbol。
- 与其他语言不通,ECMAScript没有整数和浮点数值分别定义不通的数据类型,Number类型可以用于表示所有数值。
- ECMaScript中也有一种复杂的数据类型,即Object类型,该类型是这门语言中所有对象的基础类型。
- 严格模式为这门语言中容易出错的地方施加了限制。 ECMAScript提供了很多与C及其他类C语言中相同的基本操作符,包括算数操作符、布尔操作符、关系操作符、相等操作符及赋值操作符等。
- ECMAScript从其他语言中借鉴了很多流程控制语句,例如if语句、for语句和switch语句等。
- 无须指定函数的返回值,因为任何ECMAScript函数都可以在任何时候返回值,实际上,未指定返回值的函数返回的是一个特殊的undefined值。
- ECMAScript中也没有函数签名的概念,因为其函数参数是以一个包含零或多个值的数组的形式传递的。
- 可以向ECMAScript函数传递任意数量的参数,并且可以通过arguments对此昂来访问这些参数。
- 由于不存在函数签名的特性,ECMAScript函数不能重载。