ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 变量类型 JavaScript 是一种弱类型脚本语言,所谓弱类型指的是定义变量时,不需要什么类型,在程序运行过程中会自动判断类型。 ECMAScript 中定义了 6 种原始类型: * Boolean * String * Number * Null * Undefined * Symbol(ES6 新定义) **注意**:原始类型不包含 Object。 > 题目:类型判断用到哪些方法? ### `typeof` `typeof xxx`得到的值有以下几种类型:`undefined boolean numbe string object function`、`symbol`,比较简单,不再一一演示了。这里需要注意的有三点: * `typeof null`结果是`object`,实际这是`typeof`的一个bug,null是原始值,非引用类型 * `typeof [1, 2]`结果是`object`,结果中没有`array`这一项,引用类型除了`function`其他的全部都是`object` * `typeof Symbol()`用`typeof`获取`symbol`类型的值得到的是`symbol`,这是 ES6 新增的知识点 ### `instanceof` 用于实例和构造函数的对应。例如判断一个变量是否是数组,使用`typeof`无法判断,但可以使用`[1, 2] instanceof Array`来判断。因为,`[1, 2]`是数组,它的构造函数就是`Array`。同理: ~~~ function Foo(name) { this.name = name } var foo = new Foo('bar') console.log(foo instanceof Foo) // true ~~~ > 题目:值类型和引用类型的区别 ### 值类型 vs 引用类型 除了原始类型,ES 还有引用类型,上文提到的`typeof`识别出来的类型中,只有`object`和`function`是引用类型,其他都是值类型。 根据 JavaScript 中的变量类型传递方式,又分为**值类型**和**引用类型**,值类型变量包括 Boolean、String、Number、Undefined、Null,引用类型包括了 Object 类的所有,如 Date、Array、Function 等。在参数传递方式上,值类型是按值传递,引用类型是按共享传递。 下面通过一个小题目,来看下两者的主要区别,以及实际开发中需要注意的地方。 ~~~ // 值类型 var a = 10 var b = a b = 20 console.log(a) // 10 console.log(b) // 20 ~~~ 上述代码中,`a``b`都是值类型,两者分别修改赋值,相互之间没有任何影响。再看引用类型的例子: ~~~ // 引用类型 var a = {x: 10, y: 20} var b = a b.x = 100 b.y = 200 console.log(a) // {x: 100, y: 200} console.log(b) // {x: 100, y: 200} ~~~ 上述代码中,`a``b`都是引用类型。在执行了`b = a`之后,修改`b`的属性值,`a`的也跟着变化。因为`a`和`b`都是引用类型,指向了同一个内存地址,即两者引用的是同一个值,因此`b`修改属性时,`a`的值随之改动。 再借助题目进一步讲解一下。 > 说出下面代码的执行结果,并分析其原因。 ~~~ function foo(a){ a = a * 10; } function bar(b){ b.value = 'new'; } var a = 1; var b = {value: 'old'}; foo(a); bar(b); console.log(a); // 1 console.log(b); // value: new ~~~ 通过代码执行,会发现: * `a`的值没有发生改变 * 而`b`的值发生了改变 这就是因为`Number`类型的`a`是按值传递的,而`Object`类型的`b`是按共享传递的。 JS 中这种设计的原因是:按值传递的类型,复制一份存入栈内存,这类类型一般不占用太多内存,而且按值传递保证了其访问速度。按共享传递的类型,是复制其引用,而不是整个复制其值(C 语言中的指针),保证过大的对象等不会因为不停复制内容而造成内存的浪费。 引用类型经常会在代码中按照下面的写法使用,或者说**容易不知不觉中造成错误**! ~~~ var obj = { a: 1, b: [1,2,3] } var a = obj.a var b = obj.b a = 2 b.push(4) console.log(obj, a, b) ~~~ ![](https://img.kancloud.cn/e6/0a/e60a0276151e26500786cb889c7173d2_321x413.png) 虽然`obj`本身是个引用类型的变量(对象),但是内部的`a`和`b`一个是值类型一个是引用类型,`a`的赋值不会改变`obj.a`,但是`b`的操作却会反映到`obj`对象上。