字面量:用来为变量赋值时的常数量。
对象字面量
对象字面值是封闭在花括号对({})中的一个对象的零个或多个"属性名:值"列表。
var person={
"name":"Jack",
"age":29,
5:true // 这里的数值属性,不能使用传统的点访问符,需要使用数组访问符
}
console.log(person.name) // Jack
console.log(person[5]) // true
console.log(person.5) // Uncaught SyntaxError: missing ) after argument list
console.log(person.'5') // Uncaught SyntaxError: Unexpected string
除了数字之外,其它非法标识符例如 空格、感叹号甚至空字符串,都可以用于属性名称中,当然访问这些属性仍然只能用数组访问符。
在通过对象字面量定义对象时,实际上不会调用Object构造函数(Firefox 2及更早版本会调用Object构造函数;但Firefox3之后就不会了)。这是因为字面量法创建对象强调该对象仅是一个可变的hash映射,而不是从对象中提取的属性或方法。
增强性字面量支持
在es6中,对象字面量的属性名可以简写、方法名可以简写、属性名可以计算。例如:
var name = "nana", age = 20, weight = 78
var obj = {
name, // 等同于 name: nana
age, // 等同于 age: 20
weight, // 等同于 weight: 78
sayName() { // 方法名简写,可以省略 function 关键字
console.log(this.name);
},
// 属性名是可计算的,等同于over78
['over' + weight]: true
}
console.log(obj) // {name: "nana", age: 20, weight: 78, sayName: ƒ, over78: true}
注意每个对象元素之间,需要以逗号分隔,每个元素没有字面上的键名,但其实也是一个键值对。
甚至在创建字面量对象时,可以使用隐藏属性__proto__设置原型,并且支持使用super调用父类方法:
var superObj = {
name: "nana",
toString(){
return this.name
}
}
var obj = {
__proto__: superObj,
toString() {
return "obj->super:" + super.toString();
}
}
console.log(obj.toString()) // obj->super:nana
属性赋值器(setter)和取值器(getter),也是采用了属性名简写:
var cart = {
wheels: 4,
get wheels () {
return this.wheels
},
set wheels (value) {
if (value < this.wheels) {
throw new Error(' 数值太小了! ')
}
this.wheels = value;
}
}
因为有增加性的属性名、方法名简写,当在CommonJS 模块定义中输出对象时,可以使用简洁写法:
module.exports = { getItem, setItem, clear }
// 等同于
module.exports = {
getItem: getItem,
setItem: setItem,
clear: clear
}
内置类型
JS 中分为七种内置类型,七种内置类型又分为两大类型:基本类型和对象(Object)。
基本类型有六种: null
,undefined
,boolean
,number
,string
,symbol
。
其中 JS 的数字类型是浮点类型的,没有整型,都采用64位浮点类型存储。并且浮点类型基于 IEEE 754标准实现,在使用中会遇到某些 Bug。NaN
也属于 number
类型,并且 NaN
不等于自身,NaN是唯一一个不等于自身的JS常量。
typeof
typeof
对于基本类型,除了 null
都可以显示正确的类型。
typeof
对于对象,除了函数都会显示 object。
对于 null
来说,虽然它是基本类型,但是 typeof
null
会显示 object
,这是一个存在很久了的 Bug。
如果我们想获得一个变量的正确类型,可以通过 Object.prototype.toString.call(xx)
。这样我们就可以获得类似 [object Type]
的字符串。
整数字面量
JS整数共有四种字面量格式:十进制、二进制、八进制、十六进制。JS整数也属于浮点类型,JS没有整型。
对于非十进制,如果超出了数值范围,则会报错。
- 八进制
八进制字面值的第一位必须是0,然后是八进制数字序列(0-7)。如果字面值中的数值超出了范围,那么前导0将被忽略,后面的数值被当作十进制数解析。例如:
var n8 = 012
console.log(n8) //10
var n8 = 09
console.log(n8) //9
- 十六进制
十六进制字面值的前两位必须是0x,后跟十六进制数字序列(0-9,a-f),字母可大写可小写。如果十六进制中字面值中的数值超出范围则会报错。
var n16 = 0x11
console.log(n16) //17
var n17 = 0xw //Uncaught SyntaxError: Invalid or unexpected token
- 二进制
二进制字面值的前两位必须是0b,如果出现除0、1以外的数字会报错。
var n2 = 0b101
console.log(n2) //5
var n3 = 0b3 //Uncaught SyntaxError: Invalid or unexpected token
JS浮点数并不精确,0.1+0.2 != 0.3
console.log(0.1+0.2 === 0.3) //false
console.log(0.3/0.1) //2.9999999999999996
console.log((0.3 - 0.2) === (0.2 - 0.1)) // false
为什么会不精确?
人类写的十进制小数,在计算机世界会转化为二进制小数。对于上面提到的 0.3 这个是进制小数,换算成二进制应该是什么呢?
0.01 = 1/4 = 0.25 //小
0.011 =1/4 + 1/8 = 0.375 //又大了
0.0101 = 1/4 + 1/16 = 0.334 //还大
0.01001 = 1/4 + 1/32 = 0.28125 //又小了
0.010011 = 1/4+ 1/32 + 1/64 = 0.296875 //接近了
根据国际标准IEEE754,JS的64位浮点数的二进制位是这样组成的:
1: 符号位,0正数,1负数
11: 指数位,用来确定范围
52: 尾数位,用来确定精度
后面的有效数字部分,最多有52个bit。这52个bit用完了,如果仍未准确,也只能这样了。在做小数比较时,比较的是最后面52位bit,它们相等才是相等。所以,0.1 + 0.2不等于0.3也不稀奇了,在数学上它们相等,在计算机它们不等。
字符串字面量
字符串字面量,并不完全等于字符串对象。它可以使用字符串对象的所有方法,但它无法创建并保持属性:
var a = "123"
console.log(a.length) //3
a.abc = 100
console.log(a.abc) //undefined
a = new String("123")
a.abc = 100
console.log(a.abc) //100
可以认为,使用字符串字面量创建的对象均是临时对象,当调用字符串字面量变量的方法或属性时,均是将其内容传给String()重新创建了一个新对象,所以调用方法可以,调用类似于方法的属性(例如length)也可以,但是使用动态属性不可以,因为在内存堆里已经不是同一个对象了。
想象这个场景可能是这样的:
程序员通过字面量创建了一个字符串对象,并把一个包裹交给了他,说:“拿好了,一会交给我”。字符串对象进CPU车间跑了一圈出来了,程序员一看包裹丢了,问:“刚才给你的包裹哪里去了?”。字符串对象纳闷:“你什么时候给我包裹了?我是第一次见到你。”
模版字符串字面量
在es6中,提供了一种模板字符串,使用反引号(`)定义,这也是一种字符串字面量。
使用模板字符串,原来需要转义的特殊字符例如单引号、双引号,都不需要转义了。反引号中的所有空格和缩进和换行都是有效字符。
标签模板字面量 过滤HTML字符串,防止用户输入恶意内容:
function filterSpitefulCode(strings,...values){
return strings.reduce((s,v,idx)=>{
if(idx>0){
const prev=values[idx-1].replace(/</g,"<")
.replace(/>/g,">")
s+=prev
}
return s+v
},'')
}
const badCode= '<script>alert("abc")</script>'
const message=filterSpitefulCode`<p>${badCode} has been transformed safely~`
console.log(message)
// <p><script>alert("abc")</script> has been transformed safely~
正则表达式字面量
var re = /[a-z]/gi // 使用字面量创建
console.log("abc123XYZ".replace(re,"")) // 123
var re = new RegExp("[a-z]", "gi") //使用标准形式创建
常用的模式修饰符有:
g 全局匹配
m 多行匹配
i 忽略大小写匹配
在es5之前,使用字面量创建的正则,如果正则规则相同,则它们是同一个对象。这种bug在es5中已经得到修正。
数组字面量
数组字面量尾部逗号会忽略,但中间的不会
var myList = ['home',,'school',]
console.log(myList.length) // 3
var myList = ['home',,'school',,]
console.log(myList.length) // 4
函数字面量