JavaScript中的语法

本文根据JavaScript标准参考教程-阮一峰 中的语法一节内容所做的笔记, 文中会有代码来自参考文章

数值

数值范围及精度

JavaScript中所有数字都是以64位浮点数形式存储, 在某些情况下会将64位浮点数自动转为32

JavaScript中采用IEEE754存储
第一个位为符号位, 0为正, 1为负
2-12位位指数部分(11位)
13-64位为小数部分也是有效数字部分(52位)

由于指数部分有11位则JavaScript表示的范围为 (21023,21024] ( 2 − 1023 , 2 1024 ] (注意左开区间符, 右闭区间符)
当大于 21024 2 1024 (正向溢出) 返回Infinity, 小于 21023 2 − 1023 (负向溢出)返回0

Number.MAX_VALUE=1.7976931348623157e+308 表示最大值
Number.MIN_VALUE=5e-324表示最小值(大多数浏览器)

当数字的整数部分多余21位时, 或小数点后的0大于等于6个时采用科学计数法

由于IEEE的表示法, +0-0的表示也不相同,但是他们等价
区别: 1/+0 返回+Infinity, 1/-0返回-Infinity

NaN和Infinity

NaN的数据类型为Number, 但是它表示非数值not a number.

  • typeof NaN 返回"number"
  • 任何涉及NaN的运算都返回NaN
  • NaN不等于NaN
  • 0/0NaN

Infinity表示无穷, +Infinity-Infinity分别表示正无穷和负无穷

1/0     //+Infinity
1/-0    //-Infinity
//Infinity和NaN比较返回false
0*Infinity  // NaN

Infinity和数字之间的四则运算

5 * Infinity // Infinity
5 - Infinity // -Infinity
Infinity / 5 // Infinity
5 / Infinity // 0

Infinity0

0 * Infinity // NaN
0 / Infinity // 0
Infinity / 0 // Infinity

Infinity之间的运算

Infinity + Infinity // Infinity
Infinity * Infinity // Infinity
Infinity - Infinity // NaN
Infinity / Infinity // NaN

Infinitynull的计算可以看成Infinity0计算

null * Infinity // NaN
null / Infinity // 0
Infinity / null // Infinity

Infinityundefined计算全部返回NaN

undefined + Infinity // NaN
undefined - Infinity // NaN
undefined * Infinity // NaN
undefined / Infinity // NaN
Infinity / undefined // NaN

isNaN()用于判断一个值是否是NaN, 是则返回true

isNaN(NaN)  //true
isNaN(1)    //false

当传入非数值时, 看能否先转换成数值, 再判断. 如若传入的时字符串, 则会先转换为NaN, 再返回true

isNaN('23') //false
isNaN(true) //false
isNaN(0*Infinity)   //true, 0*Infinity值为NaN

传入空数组或只有一个数值成员的数组时, 返回false

数值转换

parseInt()只会返回一个十进制数或者NaN, 它从头开始解析并尽力转换为数值

parseInt('  123asf')    //123
parseInt('a23afd')  //NaN
parseInt('fas') //NaN

parseInt()可接受第二个参数,表示基数(取值为2-36), 基数为几待转换值(第一个参数)就被视为是几进制
基数若超出返回则自动转为NaN

parseInt('12', 8)   //10, 将'12'视为八进制, 转换为十进制的10
parseInt('12', 80)  //NaN

基数若是0, undefined, null则忽略基数参数

parseInt('12', 0)   //12
parseInt('12', undefined)   //12
parseInt('12', null)    //12

isFinite()返回布尔值, 表示某个值是否为正常的数值, 若是则返回true, 反之返回false

isFinite(2) //true
isFinite(Math.pow(2, 1025)) //false, Math.pow(2, 1025)超过了JavaScript所能表示的范围, 见前文

isFinite()+/-Infinity, NaN, undefined返回false, 其他都返回true

isFinite(Infinity)  //false
isFinite(NaN)   //false
isFinite(undefined) //false

字符串

字符串是不可变的,字符串中一个换行的两种表示

var s1 = `通过esc下面的键
断行` //注意使用的是键盘esc下面的键(`), 不是单引号

var s2 = "这有\n断行" //使用转义字符\n

转义字符中注意下面几个:

\HHH    //HHH为Unicode的码店
\xHH    //HH为Unicode的码店
\uHHHH  //HHHH为Unicode的码店

'\a' `//会忽略反斜杠

字符串可以视为数组, 可以通过数组属性获取值, 但无法通过数组的属性更改任何值

var s = 'asdf'
console.log(s[0])   //'a'
console.log(s[3])   //'f'

//但是无法更改
s[0] = '3'
console.log(s)  //'asdf', 'a'并没有变为'3'

//这对length属性也同样适用
s.length = 5            //先设置length属性值
console.log(s.length)   //返回的还是4, 并没有改变

字符集

JavaScript使用Unicode字符集, JavaScript引擎内部所有字符都使用Unicode表示
但在解析代码时会将Unicode转换为字面形式
JavaScript在内部以16位的UTF-16进行存储字符

Base64转码

Base64可以将任意值转换为0-9,a-z, A-Z,+,- 共64个字符(主要为了简化程序)
btoa()将任意值转为Base64编码

var base = btoa('abcd')
console.log(base)   //"YWJjZA=="

atob()Base64编码转为原来的值

var str = atob(base)
console.log(str)    //"abcd"

对象

什么是对象

对象是一组键值对, 是一种无序的复合数据集合.

对象的所有键名是字符串, 通常我们可以省略键名的两边引号, 但是要符合标识符规范

var obj = {
    1: 'a',
    '2': 'b'
    af: 'c'     //正确
    //23af: 'd'   //这样写会报错
}
//obj中的属性1等同于'1', 可以将单引号省略. af也一样

对象使用堆内存存储, 若两个变量指向同一个对象, 则修改一个变量的属性也会映射到另一个对象

var a = {name: 'javascript'}
var b = a   //b, a 指向堆内的同一块内存
b.name = 'java'
console.log(a.name) //'java'

JavaScript规定, 如果行首是大括号, 全部解释为代码块(语句).例如: {}

若想解释为对象(表达式), 必须在大括号前加上圆括号.例如: ({})

对象的属性

对象可以通过点运算符和方括号运算符读取属性, 也可以设置属性, 新增属性
方括号运算符在读取属性时括号内的参数必须加引号

var obj = {name: 'javascript'}
obj['name'] //'javascript', 对象中的键名为字符串, 符合标识符规则的可以去掉引号
obj[name]   //undefined, 这个name是变量

数值键会自动转换成字符串所以不用加,数值键只能使用方括号

var obj = {1: 'a'}
obj[1]      //'a'
obj['1']    //'a'
obj.1   //报错, 数字键不能这样使用

对象通过Object.keys()方法查看所有属性, 返回一个数组

var myObj = {
    name: 'javascript',
    age: 20
}
var arr = Object.keys(myObj)
console.log(arr)    //['name', 'age']

对象通过delete命令删除对象的属性(成功返回true), 删除不存在的属性也返回true

var obj = {name: 'javascript'}
delete obj.name
console.log(obj.name)   //undefined

delete只有在已删除存在的属性且该属性不可删除时返回false

var obj = Object.defineProperty({}, 'p', {
  value: 123,
  configurable: false
}); //将obj的p属性定义为不可删除

obj.p // 123
delete obj.p // false

delete只能删除对象本身的属性, 无法删除继承的属性

可以用in操作符来判断对象是否包含某属性(包括继承属性), 若包含则返回true

var obj = {name: 'javascript', age: 20}
console.log('name' in obj)  //true

对象的遍历

for-in循环遍历一个对象的可遍历(enumerable)的属性(包括继承的属性)

var obj = {name: 'javascript', age: 20}

for (var key in obj) {
    console.log(key+" : " + obj[key])
}
//name : 'javascript'
//age : 20

常和hasOwnProperty()方法一起使用判断属性是否是对象自身属性

数组

概念

数组是按次序排列的一组
任何类型的数组都可以写入数组
若数组的元素还是数组就构成了多维数组

var a = [1, 2, [3.1, 3.2]]
a[2][0] //3.1

数组是一种特殊的对象(重要), 使用typeof可以返回"object", 其键名从0开始按次序排列的整数

var a = ["a", 'b']
typeof a //"object"
a[0]    //"a"

数组对于键名为数值的属性使用方括号符取值

length属性

数组的length属性返回数组的成员数量, length可以通过点操作符和方括号符取值
length的值位动态值, 等于键名中最大的整数+1(重要), 这意味着length不一定准确
length属性可写的(重要). 当length值小于数组元素个数, 则数组成员也减少
length=0, 则清空数组
length值大于数组元素个数, 则产生空位

var a = ['a', 'b']
a.length //2
a[0]    //'a'

a[4] = 4 //产生两个空位, ['a', 'b', , , 4]
a.length    //5

a.length = 0
a[0]    //undefined
a   //返回一个空数组[]

数组添加其他非数值属性时不报错(因为数组也是对象), 但是不改变length值(应为length值由键名的整数最大值决定)

var a = ['a', 'b']
a.xxx = 'x'
a   //返回['a', 'b', xxx: 'x']

数组的间名超出了数值的表示范围, 则自动转为字符串

数组的检测及遍历

可以用in运算符检测数组是否包含某键名(数组也是对象)
in对空位返回false

var a = ['a', 'b', , 'c']
0 in a  //true, 注意检测的事键名(索引), 不是值
a.map((item, index, a)=>{return index in a})    //[true, true, , true], 因为空位返回false, 所以map函数不会将其添加到数组中

for-in会遍历数组的所有属性(包括非数字键), 推荐使用forwhile遍历数组

var a = ['a', 'b']
for (var key in a) {
    console.log(a[key])  //'a', 'b'
}

forEach也可遍历数组

数组的空位

两个逗号之间没有任何值时产生空位, 例如: [1, , 3]
空位不影响length(length值由键名的整数最大值决定)
取值时视空位为undefined
delete删除数组成员时形成空位, 但是也不影响length
forEach, for-in, Object.keys()方法忽略空位, 虽然取值时将空位视为undefined(注意数组元素值为undefined时不会忽略)
空位表示这个数组没有这个元素, undefined表示数组有这个元素, 但是元素值为undefined

类数组对象

可以通过对象构造类似数组的对象(array-like object)

var obj = {
    0:'a',
    1;'b',
    length: 2
}

obj是对象不是数组, 无法使用数组其他方法, length无法自动改变
arguments对象也是array-like object, 还有大多数DOM元素集

函数

函数声明

函数的声明的三种方式

function fun(){}
var f = function(){} //匿名函数, 当此种方法的function后有函数名时只在内部有效
var f = new Function() // 最后一个参数当做函数体

重复声明函数会覆盖前面的声明
函数没有return时, 不会返回任何值,或者返回undefined
函数声明提升(重要), 采用function命令声明函数时, 整个函数像变量声明一样被提升到代码头部

add(2, 3)

function add(value1, value2) {
    return (value1+value2)
}

不能在非函数的代码块中声明函数(可能无效, 因为函数声明提升, 且JavaScript中无块级作用域)

函数的属性和方法

函数的name属性返回函数名
函数的length属性返回函数定义时参数的个数
toString()属性返回一个字符串, 内容为函数的源码(包含函数内部的注释)

function add(value1, value2) {
    return (value1+value2)
}

add.toString()
/*返回如下
"function add(value1, value2) {
    return (value1+value2)
}"
*/

函数的作用域

  • 函数内部可以读取全局变量
  • 函数内部定义的变量(局部变量)会在该作用域内覆盖同名的全局变量, 且局部变量外部无法读取
  • 函数内部存在变量提升
  • 函数本身的作用域就是声明时所在的作用域, 与运行时的作用域无关. 函数体内部声明的函数, 作用域绑定函数体内部

函数参数

参数若是原始类型(数值, 字符串等)的值则传递方式是传值传递, 若是复合类型(对象, 数组,函数等)的值则传递方式为传址传递
传址传递时, 若在函数内部替换掉整个参数值(而不是参数的某个属性)则不会影响原始值
同名的参数取最后出现的值
arguments对象包含了函数运行时的所有参数, 这个对象只可以在函数体内部使用
正常模式下arguments对象也可以再运行时修改, 严格模式下arguments是一个只读对象, 修改无效但不报错
arguments.length属性返回函数运行时的参数个数

function fn(value1, value2) {
    console.log(arguments[0])
    console.log(arguments.length)
}

fn("a", 3)  //"a", 2

闭包

函数内部可以访问外部环境的所有变量, 但是外部环境不可以访问函数内部的变量
函数内部的子函数可以读取内部变量, 因此闭包可以理解”定义在一个函数内部的函数”

function a() {
    var x = 1
    function b() {
        console.log(x)  //无法访问函数b环境中的x, 因为没有. 那么向上找到函数a环境中的x
    }
}

a() //1

闭包可以看做函数内部作用域的一个接口
闭包可以封装对象的私有属性和私有方法
function关键字出现在行首, 一律解释成语句
立即调用的函数表达式(IIFE, Immediately-Invoked Function Expression)为:

(function(){}());
(function(){})();

eval命令

eval()将字符串当做语句执行
eval在当前作用域内执行, 它没有自己的作用域

eval('console.log(2)')  //2

严格模式下, eval内部声明的变量不会影响到外部作用域, 但实际上也是也会影响外部作用域

运算符

加法运算符

两操作数想加时, 若有一个是字符串, 则另一操作数转成字符串再连接在一起
减, 除, 乘法都将字符串自动转为数值再运算
对象相加想调用valueOf()方法,在调用toString()方法, 再运算
若操作数中有一个是Date对象的实例, 那么会优先执行toString()方法

算术运算符

+,-, *, /, **, %, ++, --, 正+, 负-
余数运算符%的运算结果正负号由第一个操作数决定
余数运算可以用于浮点数的计算, 但不准确
++,--为一元运算符
正+, 负-运算符也是一元运算符, 它们可以将任何值转为数值, +的作用和Number()函数相同, -转为+的相反数

赋值运算符

=在数学中念作”等于”, 但是在计算机中时赋值符号. 表示将一个数赋值给一个变量

var a = 3   //将3赋值给变量a

if (b = 3) {
    console.log(2)  //永远会打印出2
}

if括号里应该时布尔表达式, 但是b=3是赋值, 而不是布尔表达式, 应该表示为b === 3

比较运算符

<, >, >=, <=, ==, ===

字符串之间的比较, JavaScript将依次比较单个字符的Unicode码点, 谁的先大则谁就大
对于除字符串之间的原始类型的值, 除=====外, 其余运算符将操作数先转为数值再比较
NaN与任何值(包括NaN)比较都返回false, 因为NaN和任何值(包括NaN)都不想等
对于对象, 则会转为原始类型再比较(先调用valueOf, 若返回对象再调用toString)
==将两个操作数转为同一类型再比较, ===不对操作数转换. ==中两值相等的条件是可以转换为同值, ===中两值相等的条件是同类型同值
对于复合类型的值,比较它们是否指向同一内存地址
两个对象的比较, ===比较的是地址, >,<比较的是值

var a = {age: 23}
var b = a

a.age === b.age //true
a.age > b.age   //false
a.age < b.age   //false

undefined===null返回true
!==先求===的运算结果, 再取反
==中原始类型的值会转换为数值再比较
==中复合类型和原始类型的值比较, 复合类型会转为原始类型再比较
==中undefined和null不与除这两个值之外的任何值相等
!===的运算结果相反

布尔运算符

!, &&, ||, ?:
!undefined, null, false, 0, NaN, ""(空字符串)返回true, 其他返回false
!! 等同于Boolean()函数
&&, ||是短路运算符
&&(逻辑与) 在全为true的情况下返回true, 只要有false就返回false
||(逻辑或) 在全为false的情况下返回false, 只要有true就返回true

位运算符

|, &, ~, ^, <<, >>, >>>
位运算符用来处理两个比特位(1,0)
|(按位或), 全00, 有11
&(按位与), 全11, 有00
~(取反, 否), 10, 01, 因为是二进制位则可以简记为: 数的相反数减1
^(异或), 不同为1, 相同为0, 连续对两个变量进行三次^运算会交换两个变量的值(a^=b, b^=a, a^=b)
所有位运算符只对整数有效, 遇到小数时将小数部分直接舍去(不四舍五入), 只保留整数部分(则对某小数进行两次~运算得到整数)
对其他非数值进行~运算, JavaScript会先调用Number()函数在运算
<<(左移), 将二进制数向左移动指定位(符号位不移动), 尾部补0(左移相当于乘以2的幂次方)
>>(右移), 将二进制数向右移动指定位(符号位不移动), 头部补0(右移相当于除以2的幂次方)
>>>(带符号的右移), 将一个二进制数向右移动(包括符号位), 头部补0(正数相当于>>, 负数则不是)

数据类型转换

强制转换

有三种强制类型转换函数: Number(), String(), Boolean()

Number()

  • Number()方法的参数是原始类型的值时参数为数值则不变
  • 若是字符串,如果可以解析位数值则解析, 不能则为NaN
  • 空字符串""转为0
  • true转为1false转为0
  • undefined转为NaN
  • null转为0
  • Number()方法的参数是对象时, 返回NaN, 除非是包含单个数值的数组, 具体如下
    • 调用valueOf, 若返回原始类型值则对该值调用Number()
    • valueOf返回对象, 则改为调用toString()方法
    • toString()方法返回原始类型值, 则调用Number()
    • toString()方法返回对象, 则报错

String()

String()可以将任意类型的值转为字符串

  • 数值,转为相应的字符串
  • 字符串, 不变
  • true转为"true", false转为"false"
  • undefined转为"undefined"
  • null转为"null"
  • 对象, 返回字符串”[object Object]". 若为数组, 则返回数组的字符串形式
    • 调用toString()方法, 若返回原始类型值则对该值使用String()
    • 若返回对象, 则调用valueOf()方法
    • valueOf()方法返回原始类型值, 则对该值返回String()函数
    • 若调用valueOf()方法返回对象, 则报错

Boolean()

Boolean()可以将falseundefinednull0NaN""(空字符串)转为false, 其余转为true

自动转换

123+'abc' 返回‘123abc'
if('abc') 'abc'隐式转为true
+{a:b}返回NaN
-[1,2]返回NaN
自动转换为布尔值:JavaScript遇到预期为布尔值的地方会将非布尔值自动转为布尔值, 内部调用Boolean()
自动转换为字符串:JavaScript遇到预期为字符串的地方会将非布尔值自动转为字符串
先将复合类型值转为原始类型, 再转为字符串(调用String())
自动转换为数值:JavaScript遇到预期为数值的地方会将非布尔值自动转为数值, 内部调用Number()
注意:Number(null)0Number(undefined)NaN

错误处理机制

Error实例对象

ES标准中Error实例对象必须有message属性,表示出错时的提示信息
(非ES标准属性)大多数JavaScript引擎对Error实例提供namestack属性, 分别表示错误的名称和错误的堆栈

原生错误类型

JavaScript定义了6中错误对象:SyntaxErrorReferenceErrorRangeErrorTypeErrorURIErrorEvalError
SyntaxError: 语法错误
ReferenceError:引用一个不存在的变量时发生的错误
RangeError:一个值超出了有效范围时发生的错误
主要有:数组长度为负数, Number对象的参数超出范围, 函数堆栈超过最大值
TypeError:变量或参数不是预期类型时发生的错误
如:字符串, 布尔值等使用new命令
URIErrorURI相关函数的参数不正确时抛出的错误
主要涉及encodeURI()decodeURI()encodeURIComponent()decodeURIComponent()escape()unescape()这六个函数
EvalError: eval函数没有被正确执行时发生的错误(已不再使用, 保留是为了与遗留代码兼容)

处理错误

try...catch...finally语句可以用来处理错误
try代码块中出现错误时停止执行后面的代码, catch代码块会捕获错误, 我们通常在catch中处理捕获的错误, finally用来处理最后的动作, finally代码块中的代码不管有没有错都会执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值