字面量:用来为变量赋值时的常数量。
对象字面值是封闭在花括号对({})中的一个对象的零个或多个"属性名:值"列表。
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 对于基本类型,除了 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为什么会不精确?
人类写的十进制小数,在计算机世界会转化为二进制小数。对于上面提到的 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~
常用的模式修饰符有:
g 全局匹配 m 多行匹配 i 忽略大小写匹配
在es5之前,使用字面量创建的正则,如果正则规则相同,则它们是同一个对象。这种bug在es5中已经得到修正。
数组字面量尾部逗号会忽略,但中间的不会
var myList = ['home',,'school',] console.log(myList.length) // 3 var myList = ['home',,'school',,] console.log(myList.length) // 4