数值的转换
任何数据类型转换成string类型:
- x.tostring()
- String(x)
- x + ' ' //x 为要转化的类型
转换为 boolean 类型:
- boolean(x)
- !!x //x为要转换的类型
任意类型转换为 number:
- number(''1'')===1
- parseInt('1',10)===1
- parseFloat('1.234')===1.234
- '1' - 0 ===1 //老手常用
- +'1' ===1
字符串
JavaScript 使用 Unicode 字符集。JavaScript 引擎内部,所有字符都用 Unicode 表示。每个字符在 JavaScript 内部都是以16位(即2个字节)的 UTF-16 格式储存。也就是说,JavaScript 的单位字符长度固定为16位长度,即2个字节。
连接运算符(+)可以连接多个单行字符串,将长字符串拆成多行书写,输出的时候也是单行。
var longString = 'Long '
+ 'long '
+ 'long '
+ 'string';
转义符"\":用来表示一些特殊字符
需要用反斜杠转义的特殊字符,主要有下面这些:
\0 : null(\u0000)
\b :后退键(\u0008)
\f : 换页符(\u000C)
\n : 换行符(\u000A)
\r : 回车键(\u000D)
\t : 制表符(\u0009)
\v :垂直制表符(\u000B)
' : 单引号(\u0027)
" :双引号(\u0022)
\ :反斜杠(\u005C)
反斜杠还有三种特殊用法。
(1)\HHH
反斜杠后面紧跟三个八进制数(000到377),代表一个字符。HHH对应该字符的 Unicode 码点,比如\251表示版权符号。显然,这种方法只能输出256种字符。
(2)\xHH
\x 后面紧跟两个十六进制数(00到FF),代表一个字符。HH对应该字符的 Unicode 码点,比如\xA9表示版权符号。这种方法也只能输出256种字符。
(3)\uXXXX
\u 后面紧跟四个十六进制数(0000到FFFF),代表一个字符。XXXX对应该字符的Unicode 码点,比如\u00A9表示版权符号。
'\251' // "©"
'\xA9' // "©"
'\u00A9' // "©"
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\a'// a是一个正常字符,\被省略
// "a"
length属性可以返回字符串的长度。该属性也是无法改变的,字符串内部的单个字符无法改变和增删的。
JavaScript 原生提供两个 Base64 相关的方法:
- btoa():任意值转为 Base64 编码
- atob():Base64 编码转为原来的值
var string = 'Hello World!';
btoa(string) // "SGVsbG8gV29ybGQh"
atob('SGVsbG8gV29ybGQh') // "Hello World!"
要将非 ASCII 码字符转为 Base64 编码,必须中间插入一个转码环节,再使用这两个方法。
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
对象
简单来说,对象就是一组"键值对"的集合,是一种无序的复合数据类型。
var obj = {
foo: 'Hello', //key: value
bar: 'World' //key:valre
};
对象的所有键名都是字符串(ES6 又引入了 Symbol 值也可以作为键名),所以加不加引号都可以。如果键名是数值,会被自动转为字符串。如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),且也不是数字,则必须加上引号,否则会报错。
对象的引用
如果不同的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址。修改其中一个变量,会影响到其他所有变量。
var o1 = {};
var o2 = o1;
o1.a = 1;
o2.a // 1
o2.b = 2;
o1.b // 2
上面代码中,o1和o2指向同一个对象,因此为其中任何一个变量添加属性,另一个变量都可以读写该属性。
此时,如果取消某一个变量对于原对象的引用,不会影响到另一个变量。
var o1 = {};
var o2 = o1;
o1 = 1;
o2 // {}
上面代码中,o1和o2指向同一个对象,然后o1的值变为1,这时不会对o2产生影响,o2还是指向原来的那个对象。
但是,这种引用只局限于对象,如果两个变量指向同一个原始类型的值。那么,变量这时都是值的拷贝。
var x = 1;
var y = x;
x = 2;
y // 1
上面的代码中,当x的值发生变化后,y的值并不变,这就表示y和x并不是指向同一个内存地址。
普通数据类型和对象的区别:
内存图
- 你买一个 8G 的内存条
- 操作系统开机即占用 512MB
- Chrome 打开即占用 1G 内存
- Chrome 各每个网页分配一定数量的内存
- 这些内存要分给页面渲染器、网络模块、浏览器外壳和 JS 引擎(V8引擎)
- JS 引擎将内存分为代码区和数据区
- 我们只研究数据区
- 数据区分为 Stack(栈内存)和 Heap(堆内存)
- 简单类型的数据直接存在 Stack 里
- 复杂类型的数据是把 Heap 地址存在 Stack 里,所以遇到这类问题就画图,不要分析。
基本类型没有属性,但可以 .toString 是因为创建了一个temp临时对象,当.toString 时就把 temp 里的属性拿过来后temp再被回收。
面试题
var a = 1
var b = a
b = 2
请问 a 显示是几?
var a = {name: 'a'}
var b = a
b = {name: 'b'}
请问现在 a.name 是多少?
var a = {name: 'a'}
var b = a
b.name = 'b'
请问现在 a.name 是多少?
var a = {name: 'a'}
var b = a
b = null
请问现在 a 是什么?
值类型作为函数的参数传递的是值,引用类型作为函数的参数传递的是地址(引用)。