前端学习(五十四) JavaScript-类型进阶(javaScript)

类型分为原始类型对象类型,具体看类型简介这一篇博文介绍

原始类型和对象类型的区别

原始类型的值无法更改,比如修改布尔类型,而字符串中的所有方法都是返回一个新的字符串,并不会修改原来的字符串(类似于复制了一个副本,新的副本返回)

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']

猜你喜欢

转载自blog.csdn.net/zy21131437/article/details/81285339
今日推荐