为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第14天 JavaScript高级玩法 2-1章

标签:
征文 活动

课程名称: 破解JavaScript高级玩法,成为精通 JS 的原生专家

课程章节: 2-1 数据类型的陷阱,从表象看本质!

课程讲师: Cloud

课程内容:
判断是不是Object

function isObject(obj) {
    if(typeof obj === 'object') {
        return true;
    }
    return true
}
  1. 第一个问题: 上面的方法有什么问题?

    typeof null 也是 ‘object’

  2. 第二个问题:为什么 typeof null 返回的值是 “object” ?

    追溯 javascript 第一个版本,这个版本中单个值在栈中占用32个位的存储单元,又分为两个部分,一个标记位,一个表示其它的数据,这个时候它有只有5中数据类型:

    // 类型标记位
    // 000: object  
    // 001: integer   
    // 010: double   
    // 100: string   
    // 110: boolean
    

    而 null 在机器码中的指针从0~31 位全都是0,自然标记为也是 0,而标记为是0,typeof 返回的也是0了。

    当然现在的v8引擎不是这样判断数据的,它是一个历史包袱

  3. 第三个问题: 为什么不修复这个问题?

    因为兼容性的问题,如果一改很多程序就运行不起来了,所以不得不做妥协

一元运算符+转为数字

function toNumber(val) {
  return +val;
}

上面的代码在 es5中是完全没有问题的,但在 es6 引入的新的数据类型中是会出错,如下:

const print = console.log;

function toNumber(val) {
  const result = +val;
  print(result);
  return result;
}

// 传统数据类型
toNumber(null); // 0
toNumber(undefined); // NaN
toNumber(1); // 1
toNumber("123aa"); // NaN
toNumber({}); // NaN
toNumber(true); // 1

// ES6的 bigInt和Symbol

// toNumber(10n)	// 错误
// toNumber(Symbol.for("a")) // 错误

所以我们代码要考虑向后兼容

位移转为数字

// 有符号位移
function toNumber(val) {
    return val >> 0
}
// 无符号位移
function toNumber2(val) {
    return val >>> 0
}

代码有什么问题?

上面代码问题为 数值较大是 会出现莫名的数字

本质是 32位的有符号位移和无符号位移

解析:

const print = console.log;
function toNumber(val) {
  const result = val >> 0;
  print(result);
  return result;
}
function toNumber2(val) {
  const result = val >>> 0;
  print(result);
  return result;
}

// toNumber(null); // 0
// toNumber({}); // 0
// toNumber("10x"); // 0
// toNumber("10"); // 10

// 超大的数
toNumber(Number.MAX_SAFE_INTEGER); // -1
toNumber2(Number.MAX_SAFE_INTEGER); // 4294967295

// toNumber2(Number.MAX_SAFE_INTEGER)  => 4294967295

var val = Number.MAX_SAFE_INTEGER.toString(2);
// 11111111111111111111111111111111111111111111111111111
var val1 = val.substring(0, 32);
// 11111111111111111111111111111111

var num = parseInt(val1, 2);
// 4294967295

// console.log(num)

// toNumber(Number.MAX_SAFE_INTEGER)   => -1
// 有符号数字,最高位为符号位。

// 十进制变二进制:原码 => 反码 加一(补码)
// 二进制变十进制:减一 =>反码 = 原码。

var val = Number.MAX_SAFE_INTEGER.toString(2);
// 11111111111111111111111111111111111111111111111111111

var val1 =
  val.substring(0, 32) -
  // 11111111111111111111111111111111

  // 减1
  // 11111111111111111111111111111110

  // 取反,
  // 00000000000000000000000000000001  = 1

  // 因为其最高位1是负数
  1;

字符串批量转换为整数

const arr = ["1","2","3"]
arr.map(parseInt)
  • 问题1:结果是多少?

    结果为 [ 1, NaN, NaN ]

    上面代码翻译如下:

    ["1", "2", "3"].map((val, index) => parseInt(val, index));
    // parseInt("1",0)	// 这个0是没有生效的所以默认为 10进制
    // parseInt("2",1)	// 这个是1进制,但结果是为 2,1进制是不能出现2的,所以返回 NaN
    // parseInt("3",2)	// 这个是2进制,但结果是为 3,2进制是不能出现3的,所以返回 NaN
    
  • 问题2:parseInt第二个参数的取值范围

    范围为 2~36 的整数

if条件判断

const result = {}
//name存在
if(result.name) {
    result.name = obj.name
}
return result;
  • 上面的代码是否能进入if

    不能 因为对象上没有name,返回 undefined,undefined在if条件中会转为boolean值,undefined转boolean为false

    这里推荐使用 Object.hasOwnProperty() 进行判断对象上是否存在某个属性

  • 问题:那些值转为布尔值为false

    null、undefined、’’、false、(±)0、NaN

宽松比较

null == 0		// false
'0' == false	// true

本质:隐式转换

隐式转换七大法则(规律)

  1. NaN

    它和任何人都不能包括,包括它自己

  2. bigInt,Symbol

    首先比较是不是同类型,如果不是就不相等

  3. null、undefined

    null只会和null或undefined相等,undefined也是一样

  4. 布尔类型(boolean)和其它类型的相等比较

    布尔类型(boolean)会转为数字

  5. 数字类型(Number)和 字符串类型(String)的相等比较

    字符串(String)会转为数字

  6. 对象类型({})和 原始类型 的相等比较

    对象会转为原始数据类型

  7. 对象和对象相等比较

    比两个对象的引用是否同一个地址

其它

  • typeof 性能比 instanceof 性能高20倍?

    千万级别的时候性能相差 1~2倍

    // instanceOf 性能
    
    var count = 10000000;
    var func = function () {};
    
    
    var startTime = new Date();
    console.log(typeof func === "function");
    for (var j = 0; j < count; j++) {
     typeof func === "function";
    }
    
    console.log(
     '[typeof func === "function"] ' + (new Date().getTime() - startTime.getTime())
    );
    
    /* ---------- */
    
    startTime = new Date();
    console.log(func instanceof Function);
    for (var k = 0; k < count; k++) {
     func instanceof Function;
    }
    console.log(
     "[func instanceof Function] " + (new Date().getTime() - startTime.getTime())
    );
    
  • null 和 undefined实现机制完全不一样

    null 是属于关键字

    undefined 是属于一个词,变量

    代码测试:

    // null和undefined
    var print = console.log;
    print("null=》", Object.getOwnPropertyDescriptor(global, "null"));
    print("undefined=》", Object.getOwnPropertyDescriptor(global, "undefined"));
    

    上面代码运行后可以看见,null 是没有值的,undefined有描述信息。

    由此可见 null 是关键字,undefined是一个值

  • 判断是不是数字,NaN

课程收获:
对js数据类型有了深刻的理解
图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
10
获赞与收藏
5

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消