duuliy

类型总结

2018-1-23

1.判断类型:object.prototype.toString.call(“”) 包括函数 数组 对象 甚至JSON 非常牛逼

  Object.prototype.toString.call( "abc" );   ===》object string

  Object.prototype.toString.call( 42 ); // "[object Number]" 

拆封:

var a = new String( "abc" ); var b = new Number( 42 ); var c = new Boolean( true ); 
a.valueOf(); // "abc" b.valueOf(); // 42 c.valueOf(); // true
var a = new String( "abc" ); var b = a + ""; // b的值为"abc"  

typeof a;       // "object" typeof b;       // "string"

除非万不得已,否则尽量不要使用 Object(..)/Function(..)/RegExp(..):

a.instanceof 不能判断基本类型
b.constructor 构造函数可变导致类型判断不稳定
c.typeof 不能判断引用类型

2.JSON.stringify() 妙用:

var a = {      b: 42,     c: "42",     d: [1,2,3]  }; 

//第二个参数可以是数组或者函数
JSON.stringify( a, ["b","c"] ); // "{"b":42,"c":"42"}" 

//会循环第一个参数k得到a的键和下标,循环v得到值,并且会循环d里面的数组
JSON.stringify( a, function(k,v){     if (k !== "c") return v; } ); // "{"b":42,"d":[1,2,3]}"

//JSON.string 还有一个可选参数 space,用来指定输出的缩进格式。space 为正整数时是指定 每一级缩进的字符数,它还可以是字符串,此时最前面的十个字符被用于每一级的缩进:
//缩进字符串最长不能超过 10 个字符长。如果字符串长度超过了 10 个,结果中将只出现前 10 个字 符。
var a = {      b: 42,     c: "42",     d: [1,2,3]  }; 

JSON.stringify( a, null, 3 ); // "{ //    "b": 42, //    "c": "42", //    "d": [ //       1,  //       2, //       3 //    ] // }" 

JSON.parse(JSON.stringify(arr)) 可以做深拷贝!!! 转出来的undefined还是undefined,只不过打印对象的话是一个空的object,undefined会被忽略!!!!!!
这里不能转换函数,会报错
function、正则、Symbol都不行,包括对象的属性指向函数toString都不行。

过程:
(1) 如果存在 toJSON()方法而且能通过它取得有效的值,则调用该方法。否则,返回对象本身。
(2) 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值。
(3) 对第(2)步返回的每个值进行相应的序列化。
(4) 如果提供了第三个参数,执行相应的格式化。
JSON.parse()方法也可以接收另一个参数,该参数是一个函数,将在每个键值对儿上调用。

3.==和===
==会隐式强制类型转换,so===效率高 百万分一秒。。
两边值有 true,false,[],””,0,,尽量不要用==,但是可以===。

<=在js中是“不大于”的意思:(js是这样处理的)
如果a<b和a==b是false,但是结果却是a<=b和a>=b的结果是true呢???? a<=b被处理为a>b,然后将架构反转。因为b<a的结果是false,所以a<=b结果是true。

4.对象在转换类型的时候,会执行原生方法ToPrimitive。
如果Symbol.toPrimitive()方法,优先调用再返回
其算法如下:
如果已经是 原始类型,则返回当前值;
如果需要转 字符串 则先调用 toSting方法,如果此时是 原始类型 则直接返回,否则再调用 valueOf方法并返回结果;
如果不是 字符串,则先调用 valueOf方法,如果此时是 原始类型 则直接返回,否则再调用 toString方法并返回结果;
如果都没有 原始类型 返回,则抛出 TypeError类型错误。
当然,我们可以通过重写 Symbol.toPrimitive来制定转换规则,此方法在转原始类型时调用优先级最高。
原始类型的实质:!!!!

var obj = &#123;
  value: 3,
  valueOf() &#123;
    return 4;
  &#125;,
  toString() &#123;
    return '5'
  &#125;,
  [Symbol.toPrimitive]() &#123;
    return 6
  &#125;
&#125;

5.关于lodash的clonedeep
支持正则,时间data对象
函数不支持,拷贝出来是空对象,但对象的属性指向函数可以深拷贝,也就是直接拷贝函数不行,对象里面的函数可以。
原生 DOM/BOM ,原型链怎么处理…

6.环
环就是对象循环引用,导致自己成为一个闭环,例如下面这个对象:
var a = {}
a.a = a

深拷贝时,JSON.parse(JSON.stringify(obj)) 直接爆栈
拷贝之前可向 new WeakMap() 测试是否拷贝,若已拷贝直接get出来。

7.引用数据类型,如果是uduoge变量多个引用的话,引用地址不同,不会随着变化而变化
也就是说变量a和b(被const出来)第一层是两个不同的引用地址,但第二层是同一个。

let a=&#123;name:"li"&#125;
const b=[a]
a.name=666
console.log(b)   // b=[&#123;name: 666&#125;]
//如果:
let a=&#123;name:"li"&#125;
const b=[a]
a=666
console.log(b)   // b=[&#123;name:"li"&#125;]

8.NaN (not a number) 所以是number的类型 NaN===NaN ——false

9.String 转换
先调用对象自身的toString方法。如果返回原始类型的值,则对该值使用String函数,不再进行以下步骤。
如果toString方法返回的是对象,再调用原对象的valueOf方法。如果valueOf方法返回原始类型的值,则对该值使用String函数,不再进行以下步骤。
如果valueOf方法返回的是对象,就报错。
toString与String()区别:前者不能是null,undefined(这两个没有前者方法),后者可以都可以通用,是null或undefined就返回他们本身
二进制:.toString(2);
八进制:.toString(8);
十进制:.toString(10);
十六进制:.toString(16);

10.Number 转换
首先调用obj.valueOf方法, 结果返回对象本身;于是,继续调用obj.toString方法,这时返回字符串[object Object],对这个字符串使用Number函数,得到NaN。

11.小技巧
let s = Object.prototype.toString;
alert( s.call(123) ); // [object Number]
alert( s.call(null) ); // [object Null]
alert( s.call(alert) ); // [object Function]

12.instanceof
只关心原型链,不关心构造函数class(es6),原理就是原型链

13.除了下述 6 个值转换结果为 false,其他全部为 true:

undefined
null
-0
// 0或+0
NaN
'' 

14.
5-‘’k‘’ ‘’-‘’ 强制转化为number, 5+‘’k‘’ +强制转化为string
前者为NaN 后者为

15.Object.prototype.toString.call(obj)

这里市面上的深拷贝都不支持函数,函数处理方式:
在JS种有两种函数,一种是普通函数,另一种是箭头函数。每个普通函数都是 Function的实例,而箭头函数不是任何类的实例,每次调用都是不一样的引用。那我们只需要 处理普通函数的情况,箭头函数直接返回它本身就好了。
那么如何来区分两者呢?
答案是: 利用原型。箭头函数是不存在原型的。
箭头函数直接返回自身
过程见笔记

16.扩展起来,是否是数组.
扩展答案
[].slice (能力判断 )
[] instanceof Array(类型判断)
[].proto === Array.prototype
Array.isArray([]) 存在兼容问题