目录
一、基本类型
对语言引擎和开发人员来说, 类型是值的内部特征,它定义了值的行为,以使其区别于其它值。如对Number类型的值进行数学运算,对String类型的值进行字符串操作。
简单数据类型:String, Number, Boolean, Undefined, Null, Symbol, BigInt
特性
-
值是不可变的
-
存放在栈区
原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。 -
比较是值的比较
var a = 1;
var b = true;
console.log(a == b); // true
console.log(a === b); // false
通过=赋值得到的两个基本类型a和b可以记为两家连锁店,两者之间相互独立。
通过=赋值得到的两个引用类型a和b可以记为一家店里的两把钥匙,指向的都是同一家店。
null 和undefined
null表示"没有对象",代表一个空对象指针,即该处不应该有值。
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
Object.prototype.__proto__ // null
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。
(1)变量被声明了,但没有赋值时,就等于undefined。
(2)对象没有赋值的属性,该属性的值为undefined。
(3)调用函数时,应该提供的参数没有提供,该参数等于undefined。
(4)函数没有返回值时,默认返回undefined。
var i;
i // undefined
var o = new Object();
o.p // undefined
function f(x){console.log(x)}
f() // undefined
var x = f();
x // undefined
两者都可以通过!判断
var a = null;
var b; // undefined
!a; // true
!b; // true
二、引用类型
- 值是可变的
var a={age:20};
a.age=21;
console.log(a.age)//21
-
指针存在栈内存和实体对象存在堆内存
javascript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储指针,该指针指向堆中存储的对象。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。 -
比较是堆内存地址的比较
var person1 = {};
var person2 = {};
console.log(person1 == person2); // false
因为比较的是引用(即堆内存中的地址),所以两个对象不相等。

要比较两个对象是否相等需要遍历两个对象的属性,对于只有一层的对象可以这样对比,但是有多层嵌套对象时难以处理。
可以使用Underscore的isEqual()函数。_.isEqual(a,b) //true/false
参考
JavaScript 中,如何判断两个对象是否相等?
var a={age:20};
var b=a;
b.age=21;
console.log(a.age==b.age)//true
这里直接赋值,所以a和b的指针和实体对象都相同,因此,改变其中任何一个变量,都会相互影响。

此时,如果取消某一个变量对于原对象的引用,不会影响到另一个变量。
var a={age:20};
var b=a;
a = 1;
b // {age:20}
上面代码中,a和b指向同一个对象,然后a的值变为1,这时不会对b产生影响,b还是指向原来的那个对象。
三、类型判断
typeof
typeof可以判断Number、Boolean、String、Symbol、Object、Undefined、Function,9种数据类型。但是Array和Null都会返回Object
typeof 1; // number
instanceof
A instanceof B 判断A是否为B的实例。除了9种类型,还可以判断Array、RegExp。
[] instanceof Array; //true
不能判断Null和Undefined,返回Uncaught ReferenceError: ... is not defined
constructor
直接使用返回的是其构造函数

除了9种类型,还可以判断Array、RegExp,不能判断Null和Undefined
[].constructor == Array; //true
Object.prototype.toString.call()
可以判断所有类型。获取Object原型上的toString方法,让方法执行,让toString方法中的this指向第一个参数的值。toString它的作用是返回当前方法执行的主体(方法中的this,这里绑定为括号内的第一个参数)所属类的详细信息
返回第一个参数Object代表当前实例是对象数据类型(这个是固定死的),第二个参数代表的是this所属的类
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window是全局对象global的引用
四、类型转换

valueof() 和toString()
就记住:
如果有运算符:必定调用valueOf
如果对象有valueOf或toString改写:console.log()先调用改写的方法,如果两者都改优先valueOf;alert()如果没有运算符,始终调用toString
这题考查valueOf()与toString()的区别。
在不重写这两个方法时:
toString()方法:返回对象的字符串表示
valueOf()方法:返回指定对象的原始值。
默认情况,会调用toString()方法。例如:
从上面的代码来看,默认情况会调用对象的toString()方法,返回对象的字符串表示。
下面看看重写对象的toString()与valueOf()方法,并且同时存在时会发生什么:
二者并存的情况下,在数值运算中,优先调用valueOf,字符串运算中,优先调用toString。而’ '+bbb是字符串操作,为啥也是调用valueOf,那是因为,存在操作符,valueOf的优先级高于toString。
回到本题: alert(obj)不存在数值运算,和其他操作符,所以默认调用toString方法。
结果为:toString。
以上是alert()的情况
console.log()的情况:如果对象存在valueOf或toString改写的话,就先调用改写的方法,如果两者都有则优先valueOf。而alert()如果没有运算符,则始终是调用toString
参考:
https://segmentfault.com/a/1190000010824347
https://juejin.im/post/5da593785188256f4e7079f8#heading-20
参考资料
JavaScript的数据类型及其检测
拼多多笔试题
判断输出
var a = {}
var b = {key:"b"}
var c = {key:"c"}
a[b] = 123
a[c] = 456
console.log(a[b])
输出为456,因为键名只能为字符串,如果键名为对象,浏览器会默认调用toString() 方法,将对象变成字符串"[object Object]"。两次都输入的是对象,则键名为[Object Object]的值最终覆盖成了456。a对象最终为{[object Object]:456}。
五、类型对比
==对比,如果两者类型不同则会进行转换,类型转换的方法和顺序见下图,把String和Boolean转为Number,Object转为基本类型之后还是要转为Number,所以最终都是用Number进行比较。
Object的转换比较复杂,具体再说一下:
如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,如果得到的值不是基本类型值,则再调用toString方法(这个过程即ToPrimitive),用得到的基本类型值按照前面的规则进行比较。

举一个例子
[] == ![]
!优先于==,!会把后面的值转为Boolean,![]即!true所以结果是false,
即[] == false,遇到Boolean值要转为Number
即[] == 0,遇到Object要转为原始类型,先用([]).valueOf()得到的原始值不是基本类型,再用([]).toString()得到"",长度为0的空字符串
即"" == 0,Object转为String之后再要转为Number
即0 == 0,所以为true
再举一个看上去很像的坑
[] == []
[] == {}
因为[]和{}都是属于Object,引用类型之间比较的是两个引用值在内存中是否是同一个对象。因为此 [] 非彼 [],虽然同为空数组,却是两个互不相关的空数组。所以为false
再举几个例子,想想答案,再console看看
console.log("[] == 0 ? " + ([] == 0));
console.log("['0'] == 0 ? " + (['0'] == 0));
console.log("['1'] == 0 ? " + (['1'] == 0));
console.log("[0,'1'] == 0 ? " + ([0,'1'] == 0));
console.log("['a'] == 0 ? " + (['a'] == 0));
比较运算符
var num = 1;
var str = '1';
var test = 1;
test == num //true 相同类型 相同
test === num //true 相同类型 相同值
test !== num //false test与num类型相同,其值也相同, 非运算肯定是false
num == str //true 把str转换为数字,检查其是否相等。
num != str //false == 的 非运算
num === str //false 类型不同,直接返回false
num !== str //true num 与 str类型不同 意味着其两者不等 非运算自然是tru
- == 和 != 比较若类型不同,先转换类型,再作值比较,最后返回值比较结果 。
- === 和 !== 只有在相同类型下,才会比较其值,类型不同的一定不等。
六、数据类型题
浮点数
0.1 + 0.2 === 0.3 // false
在JavaScript中的二进制的浮点数0.1和0.2并不是十分精确,在他们相加的结果并非正好等于0.3,而是一个比较接近的数字 0.30000000000000004 ,所以条件判断结果为 false
数值取整
- round() 四舍五入。
- floor() 向下取整。
- ceil() 向上取整。
- parseInt() 去掉小数,直接取整。
var a = 0.7
var b = -3.4
Math.round(a) // 1
Math.round(b) // -3
Math.floor(a) // 0
Math.floor(b) // -4
Math.ceil(a) // 1
Math.ceil(b) // -3
parseInt(a) // 0
parseInt(b) //-3
本文详细探讨了JavaScript的基础数据类型,包括基本类型的特点,null和undefined的区别,引用类型的特性和比较,以及各种类型判断方法。此外,还介绍了类型转换的规则,特别是valueOf()和toString()在不同场景下的应用。最后,文章讨论了数据类型的比较和转换,以及在实际编程中需要注意的问题,如浮点数精度问题和数值取整方法。
1796

被折叠的 条评论
为什么被折叠?



