JavaScript 进阶(五)易混淆概念null vs undefined, == vs ===, string vs String
先看一段代码
- var foo = {}
- foo.a = null
- alert(foo.a == null) //true
- alert(foo.a === undefined) //false
- alert(foo.b == null) //true
- alert(foo.b === null) //false
直观上来看,foo.a 是 null, foo.b 是undefined,所以null == undefined 为true,null === undefined 为false。null与undefined似乎都代表空,== 与 === 都代表相等判断,那么JavaScript为什么要引入这两对相似的概念,它们又有什么区别呢?我们往下看。
null 与 undefined
== 与 ===
- false == 0
- true != 2
- 1 == "1"
- true != "true"
- true == "1"
2. 对于对象(数组也是对象,String不是)
- var a = {}
- var b = a
- a == b, a === b;
- {} != {}
3. 如果是一方是对象,一方是基本数据类型呢?
- "abc" !== new String("abc")
- "abc" == new String("abc")
- 1 == new String("1") // 坑爹的string和String,下文会详细的讲“字符串”
- var a = {}
- a == "[object Object]"
- a.toString = function(){return "1";}
- a == 1
坑爹的String和string
- var a = "abc";
- typeof(a) == "string"
- var b = new String("abc")
- typeof(b) == "object"
- a == b //参考上一段的规则3,b.toString() == "abc"
- //之前一直认为a, b 都是对象, 并且类型相同,都是那个“string”,直到我今天为了写博文,测试了如下代码:
- var s1 = new String("abc");
- var s2 = new String("abc");
- s1 != s2 //what a fuck
- //其中==是比较两个string的内容,事实上 s1 != s2,所以我就纳闷了。事实上他们俩都是object,适用于上一篇的规则2.
所以代码中直接用双引号产生的string和new String出来的东西还是有点区别的。
有什么用?
我没预期过学这些东西能在我生活中起些什么实际作用,不过十年后,当我在设计第一台麦金塔(Macintosh)时,我想起了当时所学的东西,所以把这些东西都设计进了Mac里,那是第一台使用了漂亮印刷字体的电脑。如果我当时没有退学,就不会有机会去参加这个我感兴趣的美术字课程,Mac就不会有这么多丰富的字体,以及赏心悦目的字体间距。因为Windows照抄了Mac,所以现在个人电脑才能有这么美妙的字型。
上面是鸡汤啊,看起来没啥料,下面加点私货,说说我对编程中的一些所谓“冷门知识”的观点:
1. 函数重载。 比如一个库函数foo(a, b). 当调用方调用foo(a)的时候,foo函数内部的b就是undefined。在foo函数内部,检查参数是否===undefined来确定调用方到底是foo(a) 还是foo(a, null).
2. 断言。开发阶段使用断言能够让代码在出错点立刻崩溃,防止错误蔓延,从而提高调试效率。在使用断言时,要确保值和类型都正确无误,所以要使用===。3. 到底是返回null还是undefined? 对于数值计算,如果计算参数不合适,要么抛出异常,要么返回null或0作为空值。避免返回undefined,这样做会导致它的上层算式变成NaN,可能会导致错误蔓延。对于需要返回string的地方,如果出错,则要么抛出异常,要么返回空串,避免返回null或是undefined,否则就会出现“null”, "undefined"的字符串。如果应该返回对象,则应该返回null,而避免返回undefined。null和对象类型相同,防止在需要判断变量类型的地方由于一个“undefined”导致控制逻辑跑到不该去的地方。然而对于一个没有返回值的过程,则应该明确的返回undefined或是直接写return或者干脆不写return语句。4. 如果你需要判断一个对象是否拥有某一个属性,则应该使用hasOwnProperty函数。这个函数无论该属性是null还是undefined,只要属性存在,则都返回true。此外,如果你需要明确的删除一个属性,则使用delete,而不要仅仅将其置null,undefined。null,undefined不仅仅会被hasOwnProperty返回true,同时这个属性仍然是可枚举的,就是用 for - in 来遍历对象的时候仍然能够被遍历出来。5. 修改String的prototype。比如我们的代码中经常需要反转一个字符串,那么每次都这样调用reverse(s1)。这样则需要在全局名空间定义一个reverse函数。然后可以通过修改prototype来给所有的String对象提供该函数。String.prototype.reverse() = function(){}. 当这么做以后,无论是new String还是 “”字符串常量,均可以使用"abc".reverse()来返回一个反转后的字符串。6. 编写代码的时候尽量依赖内容判断而非类型。因为 == 和 === 都判断相等,。null 和 undefined都代表”无“,在阅读代码的时候很容易就直接在逻辑层面就认为它们等价了。在一段逻辑中,如果是处理数字,那么推荐在逻辑入口处将所有的入参转为数字,那么逻辑内部就不会因为== 和 ===问题出错,字符串也类似。在判断值是否为空时,尽量让分支逻辑不依赖null还是undefined。如果你的代码中typeof比较多而散布的时候,就要重新考虑一下设计的问题了。让业务逻辑层面关注内容,至于typeof,==/===, null/undefined的处理,尽量集中地放在底层库,并且由资深程序员处理。
JavaScript 进阶(五)易混淆概念null vs undefined, == vs ===, string vs String的更多相关文章
- 【C#小知识】C#中一些易混淆概念总结(五)---------继承 分类: C# 2014-02-06 22:05 1106人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(五)---------深入解析C#继承
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- C#中一些易混淆概念总结
C#中一些易混淆概念 这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念.现在给大家分享出来我的笔记: 一,.NET平台的重要组成部分都是有哪些 1)FCL (所谓的.NET框 ...
- 【C#小知识】C#中一些易混淆概念总结(七)---------解析抽象类,抽象方法
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法 分类: C# 2014-02-08 01:53 1826人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(二)--------构造函数,this关键字,部分类,枚举 分类: C# 2014-02-03 01:24 1576人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 继上篇对一些C#概念问题进行细节的剖析以后,收获颇多.以前,读书的时候,一句话一掠而 ...
- 【C#小知识】C#中一些易混淆概念总结(四)---------解析Console.WriteLine() 分类: C# 2014-02-05 17:18 1060人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结 [C#小知识]C#中一些易混淆概念总结(二) [C#小知识]C#中一些易混淆概念总结(三) ------------------------------ ...
- 【C#小知识】C#中一些易混淆概念总结(三)---------结构,GC,静态成员,静态类
目录: [C#小知识]C#中一些易混淆概念总结 [C#小知识]C#中一些易混淆概念总结(二) ---------------------------------------分割线----------- ...
- 【C#小知识】C#中一些易混淆概念总结---------数据类型存储,方法调用,out和ref参数的使用
这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念.现在给大家分享出来我的笔记: 一,.NET平台的重要组成部分都是有哪些 1)FCL (所谓的.NET框架类库) 这些类是微软 ...
随机推荐
- reason: 'unable to dequeue a cell with identifier Cell
今天在cell重用的时候出现一下错误 reason: 'unable to dequeue a cell with identifier Cell - must register ...
- randn命令中randn('state')和randn('seed')的不同
(1)RANDN产生正态分布数的语法: RANDN(N) :产生N× N的矩阵,其元素是按正态分布的数组: RANDN(M,N) and RANDN([M,N]):产生M×N的矩阵: RANDN ...
- OpenGL ES 如何能看到一个物体内部和象3dmax中能只显示网格线
上一篇 OpenGL ES 正反面设置指令 中分析了正反面的判区方法,那么正反面有什么用呢?接下来我们就要引入一个叫做背面消除的概念.在3dmax中有个选项,当你用挤压修改器挤出一个中空的长方体时,在 ...
- DE1-SOC的sof文件无法下载解决办法
按照前面友晶科技的文档介绍一步步的做,后面发现根本无法下载sof文件. 通常思维: 一,器件选错了.器件选择错误会导致sof文件无法下载,至于这个ID具体怎么识别我没有追究.如果是这种错误Quartu ...
- form验证及图片上传
form验证及图片上传 这一节增加推荐图书的提交和删除功能,来学习node的form提交以及node的图片上传功能.开始之前需要源码同学可以先在git上fork:https://github.com/ ...
- Android Support Library更新到v22.1之AppCompat新特性
构建一个可以跑在不同版本 Android 平台的软件,是非常复杂和耗时的.为了解决这个问题,Android 推出了 Android Support Library (安卓兼容包),让新的UI控件也可以 ...
- Clojure学习03:数据结构(集合)
Clojure提供了几种强大的数据结构(集合) 一.集合种类 1.vector 相当于数组,如: [2 3 5] , ["ad" "adas" & ...
- Docker 安装命令
curl -sSL https://get.daocloud.io/docker | sh
- Android:创建可穿戴应用 - 安装和依赖管理
安装可穿戴应用 在开发时,你能够像一般移动应用一样直接把应用安装到可穿戴设备中. 使用adb install或者 Android Studio上的Play button. 当你准备好要公布时,你须要把 ...
- ONOS系统架构演进,实现高可用性解决方案
上一篇文章<ONOS高可用性和可扩展性实现初探>讲到了ONOS系统架构在高可用.可扩展方面技术概况,提到了系统在分布式集群中怎样保证数据的一致性.在数据终于一致性方面,ONOS採用了Gos ...