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框架类库) 这些类是微软 ...
随机推荐
- BZOJ 3282: Tree( LCT )
LCT.. -------------------------------------------------------------------------------- #include<c ...
- Handler没法取出消息队列中的数据的一个原因
主线程发送消息到工作线程,工作线程的步骤是固定为3步的. Looper.prepare();//步骤1,线程里使用handler必须这样写, handler = new Handler(){//步骤2 ...
- PHP学习笔记6-时间/日期
时区/时间/日期 输出unix时间戳(从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数),用time() echo time();//unix时间戳 输出结果:143557475 ...
- HDU 3917 最大权闭合图 求最小割
具体参考http://blog.csdn.net/power721/article/details/6665750 TODO //#pragma comment(linker, "/STAC ...
- WEB开发:如何用js来模拟服务器的ajax响应,不依赖服务器来编写前端代码
一.问题的提出 目前web前端开发,主流的思路是: 1)编写静态的html文件(不使用模板技术,与服务器无关) 2)页面通过ajax与服务器交互,进行数据的传输,数据格式为json格式 这里存在一个问 ...
- YARN & HDFS2 安装和配置Kerberos
今天尝试在Hadoop 2.x开发集群上配置Kerberos,遇到一些问题,记录一下 设置hadoop security core-site.xml <property> <name ...
- 错误解决--oracle中出现ORA-01791: 不是 SELECTed 表达式 错误
Oracle数据库,执行下面语句出现错误“ORA-01791: 不是 SELECTed 表达式”: select distinct t.name from auth_employee t order ...
- 使用线程新建WPF窗体(公用进度条窗体)
使用线程新建窗体 项目中需要一个公用的进度条窗体.大家知道在wpf中,有两个线程,一个是UI线程,另一个是监听线程(一直监听用户的输入).如果我们后台有阻塞UI线程的计算存在,那么界面上的比如进度条什 ...
- 中科燕园GIS外包---地铁GIS项目
(1)地铁保护及project地质管理 • 地铁保护 地铁交通既有运量大,速度快的特点,又有差别于其它交通方式的在地下执行的空间特殊性,因此地铁的保护显得尤为重要. 首先必须编制完整的 ...
- CodeForces 191C 树链剖分 第4遍
非常无奈,模板重新无奈的打错了.. 只是,非常快便找到了.. 题意:给一些边,有一些操作,每次操作,都要在这些边上加上1,求每一个边的边权.. #include<cstdio> #incl ...