JS数据类型、运算符容易踩的几个坑.md

7种基本数据类型

  • 6种原始类型
    • null 表示缺少的标识,指示变量未指向任何对象。
    • undefined 是全局对象的一个属性
    • Boolean
    • Number
    • String
    • Symbol(ES6中新定义)
  • Object

另一种区分方式

1、值类型:即5种基本类型(string,number,boolean,null,undefined);

2、引用类型:即数组、函数、对象共三种。这三种类型的处理与值类型会有很大的差别。

JS中常用的内置对象

  • date时间对象
  • string字符串对象
  • Math数学对象,
  • Number数值对象,
  • Array数组对象,
  • function函数对象,
  • arguments函数参数集合,
  • Boolean布尔对象,
  • Error错误对象,
  • Object基础对象

记住以下结果

null与undefined区别

javaScript设计者最初是这样设计的:null是一个表示”无”的对象,转为数值时为0;undefined是一个表示”无”的原始值,转为数值时为NaN

后来在使用的过程中这样区分
null表示”没有对象”,即该处不应该有值。典型用法是:

(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。

undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义。典型用法是:

(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typeof null        // object (因为一些以前的原因而不是'null')
typeof undefined // "undefined"
null === undefined // false
null == undefined // true
null === null // true
undefined === undefined// true
!null //true
!undefined //true
isNaN(1 + null) // false null转化为Number时为0
isNaN(1 + undefined) // true undefined转化为Number时为NaN
1+null //1
1+undefined //NaN

//但是要记住,null能转化为Number进行计算
null == 0 //false
undefined == 0 // false

null与Object

1
2
null==Object  //false
null===Object //false
1
2
3
4
5
[]==![]  //true
[]==false //true

![] //false
!{} //false

严格相等===

两个被比较的值在比较前都不进行隐式转换

非严格相等 ==

在比较前将两个被比较的值转换为相同类型。在转换后(等式的一边或两边都可能被转换),最终的比较方式等同于全等操作符
=== 的比较方式。

关于

Object.is(A,B)

区分和严格相等===之间的区别

1
2
3
4
5
6
7
8
Object.is(-0 , +0)  //false
-0 === +0 //true

Object.is(NaN , NaN) //true
NaN === NaN //false

[1,2] == '1,2' //true
[1,2] === '1,2' //false


ToNumber

1
2
Number('')  // 0
Number('a123') //NaN
input result
null +0
undefined NaN
Boolean +0 / 1
Number 不转换
String
Symbol 报错
Object ToNumber(ToPrimitive( input , Number))

ToPrimitive()

关于隐式转换参考这篇文章:js隐式装箱-ToPrimitive

默认用法:ToPrimitive(input [,
PreferredType]),(ToPrimitive方法可被修改)

  • 如果是Date求原值,则PreferredType是String,其他均为Number。
  • PreferredType是String,则先调用toString(),结果不是原始值的话再调用valueOf(),还不是原始值的话则抛出错误;
  • PreferredType是Number,则先调用valueOf()再调用toString()。

+ -操作符

在加法的过程中,首先把等号左右两边进行了求原值ToPrimitive()操作,然后如果两个原值只要有一个是String类型,就把两个原值都进行转化字符串ToString()操作,进行字符串拼接;否则把两个原值都进行转化数字ToNumber()操作,进行数字相加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
+[]  //0
+[0] //0
+{} //NaN

[] + [] // ""
// PreferredType是Number,则先调用valueOf()再调用toString()。 []==>[]==>""

{} + {} //"[object Object][object Object]"
//{} PreferredType是Number,则先调用valueOf()再调用toString() {}==>{}==>"[object Object]"

[] + {} // "[object Object]"
//[]==>[] ==>""
//{} PreferredType是Number,则先调用valueOf()再调用toString() {}==>{}==>"[object Object]"
// 然后字符串拼接

{} + [] // 0
// 原因在于{}在前,被当成{};直接执行了,变成了 +[],[]的原值是"",+[]需要进行toNumber转换变成了0 ,最后结果为0

++[[ ]][+[ ]]+[+[ ]]
//这个就有意思了,一开始对[][]理解错了,以为是二维数组,二维数组是name[i][j],这个才是对二维数组的调用,[][]是对前面那个一维数组的调用,数组名就是第一个[].
拆分:
>> ++[[]][+[]] + [+[]] 很明显 我们知道+[]的结果是0
>> ++[[]][0] + [0] 这里我们就看到是对数组[[]]的第0位进行操作,即[]
>> ++[] + [0]
>> ([]+1) + [0]
>> (''+1) + [0]
>> '1' + [0]
>>'10'

下列表达式输出什么

1
2
3
4
5
6
console.log(1 + "2" + "2");
console.log(1 + +"2" + "2");
console.log(1 + -"1" + "2");
console.log(+"1" + "1" + "2");
console.log( "A" - "B" + "2");
console.log( "A" - "B" + 2);
1
2
3
4
5
6
'122'
'32'
'02'
'112'
'NaN2'
NaN

运算过程注意一下几点:

  • 多个数字和数字字符串混合运算时,跟操作数的位置有关
1
2
console.log(2 + 1 + '3'); // '33'
console.log('3' + 2 + 1); //'321'
  • 数字字符串之前存在数字中的正负号(+/-)时,会被转换成数字,同样,可以在数字前添加
    ‘’,将数字转为字符串
1
2
3
4
console.log(typeof '3'); // string
console.log(typeof +'3'); //number
console.log(typeof 3); // number
console.log(typeof (''+3)); //string
  • 对于运算结果不能转换成数字的,将返回 NaN
1
2
consol.log('a' * 'sd'); //NaN
console.log('A' - 'B'); // NaN

给基本类型数据添加属性,不报错,但取值时是undefined

1
2
3
4
5
6
var a = 10;
a.pro = 10;
console.log(a.pro + a); //undefined
var s = 'hello';
s.pro = 'world';
console.log(s.pro + s); //'undefinedhello'

a.pro和s.pro都为undefined。给基本类型数据加属性不报错,但是引用的话返回undefined,10+undefined返回NaN,而undefined和string相加时转变成了字符串。

A && B 与 A || B

A && B
与运算,会做boolean转换,当A为false时返回A的结果,当A为true时返回B的结果,
A||B 或运算,当A为true时返回A的结果,当A为false时返回B的结果。

instanceof运算符详解

这里有一篇博文,详细介绍的instanceof运算符的历史由来以及定义

先说typeof运算符,判断数据类型,对于基本类型,返回基本类型,对于引用类型的,不管哪一种引用类型,都返回’object’

instanceof 运算符通常用来判断一个实例是否属于某种类型,使用方法为foo instanceof Foo返回一个Boolean值
因为这个原因,更多的时候在继承关系中,用来判断实例是否属于一个父类型

instanceof如何实现这样的功能,语言规范里面有详细的介绍,这里截取js表达的方式

1
2
3
4
5
6
7
8
9
10
11
12
>function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
var O = R.prototype;// 取 R 的显示原型
L = L.__proto__;// 取 L 的隐式原型
while (true) {
if (L === null)
return false;
if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true
return true;
L = L.__proto__;
}
}
>

由规范得到,instanceof将前面表达式的__proto__与后面的表达式的prototype进行严格相等===比较,
如果相等返回true,如果不相等,则继续循环获取前面表达式的__proto__,直到 Object.__proto__===null为止返回false。

1
2
3
4
5
6
7
8
9
console.log(Object instanceof Object);//true 
console.log(Function instanceof Function);//true
console.log(Number instanceof Number);//false
console.log(String instanceof String);//false

console.log(Function instanceof Object);//true

console.log(Foo instanceof Function);//true
console.log(Foo instanceof Foo);//false