类型分为原始类型和对象类型,具体看类型简介这一篇博文介绍
原始类型和对象类型的区别
原始类型的值无法更改,比如修改布尔类型,而字符串中的所有方法都是返回一个新的字符串,并不会修改原来的字符串(类似于复制了一个副本,新的副本返回)
var a="ABC";
a.toLowerCase();
console.log(a) //输出的依旧是ABC
原始类型:相等比较
原始类型的比较是值的比较,比较的是两个类型的值是否相等(==,系统会转换成相同类型的值在比较,‘123’==123,true,===,系统不会自动转换,不光是值,类型也要相等,‘123’===123,false)
对象类型的值是可以修改的
var o={x:1};
o.y=2;
console.log(o) //{x: 1, y: 2}
对象类型:相等比较
对象类型也叫引用类型,当给一个变量赋值为对象时,该变量保存的是该对象在内存中的地址,简单的说就是在内存上开了一个空间(这段空间就是对象,存储键值对),而变量的值就是对应引用了这段内存,所以,对象的比较是比较的引用地址是否是同一个,例如:
var o={x:1};
var x={x:1}
console.log(o===x) //false,即时完全一直也是false
var x={x:1}
var y=x;
y.z=2
consile.log(x.z) //2,对y的修改就相当于在修改内存上的内容,因此对象x,也被修改了
console.log(y===x) //true
复制变量的值
就是将它赋值给另外一个变量,赋值对象类型和原始类型略有不同
var x={x:1}
var y=x;
赋值原始类型的值
会将值拷贝一份,和原来的值是相互独立的,因此修改并不会影响原值
赋值对象类型的值
会将存储在变量中的值拷贝一份给新变量,也就是它们两指向了同一个内存地址,因此修改会相互英雄
类型转换
var aa='5'+'2'; //52,字符串相连
var ab='5'-'2'; //3,5和2转换成number类型进行减法运算
console.log(aa,ab)
var ac=''-2; //-2
var ad=true+false; //1
var ae=null+1 //1
var af=undefined+1; //NaN
var ag=[]+[]; //""
console.log(ac,ad,ae,af,ag)
第一行是B,第一列是A
undefined | null | number | string | boolean | object | |
undefined | true | true | false | false | false | IsFalsy(B) |
null | true | true | false | false | false | IsFalsy(B) |
number | false | false | A===B | A===ToNumber(B) | A===ToNumber(B) | A===ToPrimitive(B) |
string | false | false | ToNumber(A)===B | A===B | ToNumber(A)===ToNumber(B) | A===ToPrimitive(B) |
boolean | false | false | ToNumber(A)===B | ToNumber(A)===ToNumber(B) | A===B | ToPrimitive(A)===ToPrimitive(B) |
object | false | false | ToPrimitive(A)===B | ToPrimitive(A)===B | ToPrimitive(A)===ToNumber(B) | A===B |
值 | 转字符串 | 转数值 | 转布尔 | 转对象 |
undefined | 'undefined' | NaN | false | TypeError |
null | 'null' | 0 | false | TypeError |
true | 'true' | 1 | new Bollean(true) | |
false | 'false' | 0 | new Bollean(false) | |
'' | 0 | false | new String('') | |
'1.2' | 1.2 | true | new String(1.2'') | |
'abc' | NaN | true | new String('abc') | |
0 | '0' | false | new Number(0) | |
-0 | '-0' | false | new Number(-0) | |
NaN | 'NaN' | false | new Number(NaN) | |
Infinity | 'Infinity' | true | new Number(Infinity) | |
-Infinity | '-Infinity' | true | new Number(-Infinity) | |
[](空数组) | '' | 0 | true | |
[9](仅有一个数组) | '9' | 9 | true | |
['a'](不是数组或多个内容) | 相当于使用了join方法 | NaN | true |
显示类型转换
推荐使用Booleab(),Number(),String(),Object()
Number("123") //123
String(123) //"123"
Boolean([]) //true
Object(3) //new Number(3)
显示类型转换:转成字符串
还可以使用toString(),它的执行结果通常和String()方法一直,Number类型的toString()方法还支持第二个参数,指定要转换的进制(注意:null和undefined没有toString方法,会报错)
(null).toString() //Error,会报错,null没有toString()方法
(undefined).toString() //Error,会报错,undefined没有toString()方法
(123).toString() //'123'
(false).toString() //"false
显示类型转换:转成数值
字符串类型转为数值还有两个全局方法:parseInt()和parseFloat()
对象类型转字符串
三种方法:value.toString(),String(value),''+value
console.log({x:1}.toString()) //[object Object]
console.log(''+{x:1}) //[object Object]
console.log(String({x:1})) //[object Object]
对象类型转数值
有两种:+varlue,Number(value)
var oa={x:1};
console.log(+oa) //NaN
console.log(Number(oa)) //NaN
类型识别
- 可以使用typeof value检测
- 也可以使用obj instanceof constructor,注意instanceof不是在获得变量的类型,而是在判断变量的类型是否与给定的相一致,不可以跨frame
var ob=new Date();
var oc=[];
var od=null;
var oe=/\d+/
console.log(ob instanceof Date) //true
console.log(oc instanceof Array) //true
console.log(od instanceof Object) //false
console.log(oe instanceof RegExp) //true
甚至自定义的构造函数也可以判断,
- constructor,检测变量的构造函数,不可以跨frame
console.log(({x:1}).constructor.name) //Object
console.log(([]).constructor.name) //Array
console.log((new Date()).constructor.name) //Date
console.log(('').constructor.name) //String
console.log((true).constructor.name) //Boolean
console.log((123).constructor.name) //Number
console.log((null).constructor.name) //TypeError,没有constructor属性,会报错
console.log((undefined).constructor.name) //TypeError,没有constructor属性,会报错
- Object.prototype.toString(推荐),检测对象的内部属性
function getType(o) {
var toString=Object.p
return Object.prototype.toString.call(o);
}
var pa=new Date();
var pb=[]
var pc=/\d+/;
console.log(getType(pa)) //[object Date]
console.log(getType(pb)) //[object Array]
console.log(getType(pc)) //[object RegExp]
方法 | 小结 |
typeof | 无法检测具体的对象类型,适合检测变量是否有定义 |
instanceof | 无法检测原始类型,跨frame失效 |
constructor | 不检查原型链,无法检测null和undefined,跨frame失效,有浏览器兼容问题,某些场景下无效 |
duck-typing | 不可靠,某些场景下失效 |
Object.prototype.toString | 可以检测所有原生对象,无法识别自定义对象的具体类型 |
最最最推荐的,是优先使用原生方法
实际开发中最常用的是检测数组,Array.isArray()
模版字面量(不会,下次在弄懂)
- 模版字面量是允许嵌入表达式的字符串字面量,可以使用多行字符串和字符串插值功能。
- 支持所有合法的JavaScript表达式,包括函数调用
- 插值表达式支持嵌套
Symbol
详细请看:https://www.cnblogs.com/ddfe/p/5609733.html
一种新的原始数据类型,表示独一无二的值。它是JavaScript语言的第七种数据类型,表示独一无二的值
想给他人创建的对象添加属性,不管该属性取什么名字,理论上都有存在冲突的可能性,而使用Symbol作为对象的属性名就没有这个顾虑,因为它的值是唯一的,这也意味着给对象添加私有属性成为了可能
- 注意:Symbol()是原始类型,不是对象,构造函数,所以不存在new这个关键字
- 注意:Symbol值作为对象属性名时,不能用点运算符,因为点运算符后面总是字符串
let name=Symbol();
let person={};
person[name]="casd"
console.log(person[name]);
console.log(name)
有时候需要在不同的地方使用同一个symbol,用来当作不同对象的唯一标识符,可以使用Symbol.for()方法完成这个功能
var uid=Symbol.for('uid');
var object={
[uid]:"1234"
}
console.log(object[uid]) //1234
console.log(uid); //Symbol[uid]
var uid2 = Symbol.for("uid");
console.log(uid === uid2); //true
console.log(object[uid2]); //1234
console.log(uid2); //Symbol[uid]
可以使用Obejct.getOwnPropertySymbols()方法查找对象的symbol属性
var uid=Symbol.for('uid');
var object={
[uid]:"1234"
}
var symbols=Object.getOwnPropertySymbols(object);
console.log(symbols.length); //1
console.log(symbols[0]); //Symbol(uid)
console.log(object[symbols[0]]); //1234
es6内置symbol
名称 | 作用 |
Symbol.hasInstance | instanceof操作符内部实现的方法 |
Symbol.isConcatSpreadable | 布尔值,Array.prototype.concat()是否要讲集合参数摊平 |
Symbol.iterator | 返回iterator的方法 |
Symbol.match | String.prototype.match()用来比较字符串的方法 |
Symbol.replace | String.prototype.replace()用来替换字符串的方法 |
Symbol.search | String.prototype.search()用来滋味子字符串的方法 |
Symbol.species | 用来创建衍生对象(derived object)的构造函数 |
Symbol.split | String.prototype.split()用来切歌字符串的方法 |
Symbol.toPrimitive | 返回对象的原始值的方法 |
Symbol.toStringTag | Obejct.prototype.toString()创建对象时的描述字符串 |
Symbol.unscopables | 一个对象,指定在使用with语句时,不应遍历的属性名称集合 |
Symbol.hasInstance
用来判断给的的对象是否是该函数的实例,它是函数原型上的方法
let a=12;
console.log(a instanceof Number) //false
console.log(Number[Symbol.hasInstance](a)); //false
Symbol.hasInstance是不能被修改不能被枚举的,所以如果要修改,要使用definProperty方法
Object.defineProperty(Number,Symbol.hasInstance,{
value:function(n){
return typeof n === "number"
}
})
Symbol.isConcatSpreadable
concat()方法用于合并两个或多个数组,默认数组元素是展开的,它的值是undefined,如果不想展开,就将它的值设为false
var a=['a','b'];
var n=[1,2];
console.log(a.concat(n,'123asd')); //["a",'b',1,2,'123asd'],5个元素
console.log(a[Symbol.isConcatSpreadable])
n[Symbol.isConcatSpreadable]=false;
console.log(a.concat(n,3))//["a",'b',[1,2],'123asd'],4个元素
另外对类数组也适用,合并是会根据length的值,查找obj[0]到obj[length-1]的值进行合并,所以必须包含0到length-1的数值属性
var ca={
0:'a',
1:'b',
2:'c',
length:2,
[Symbol.isConcatSpreadable]:true
}
let r=["abc"].concat(ca);
console.log(r.length); //3
console.log(r); //['abc','a','b']