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框架类库) 这些类是微软 ...
随机推荐
- ASP.NET路由
ASP.NET 路由使您可以使用不必映射到网站中特定文件的 URL. 由于该 URL 不必映射到文件,因此可以使用对用户操作进行描述因而更易于被用户理解的 URL. ASP.NET MVC 框架和 A ...
- ThinkPHP - CURD增删改查操作
public function show(){ //使用model模型 //1.可以使用 $user = new Model('User'); //2.可以使用 $user = M('User'); ...
- 【Hibernate】Remember that ordinal parameters are 1-based!
此错误的官方解释:1.当hql中不需要参数,而传递了参数导致,2.set参数时没有从0开始. 但此问题不属这两种. 检查导入的libraries无错误. 最后在网络搜索到:http://qihaihu ...
- UIBezierPath详解
使用UIBezierPath类可以创建基于矢量的路径,这个类在UIKit中.此类是Core Graphics框架关于path的一个封装.使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线 ...
- linux修改shell为zsh
以前使用的bash,如果目录很长,那么整个路径都被占满了. 询问一下一位大牛,答曰:zsh. 安装:ubuntu下sudo apt-get install zsh 修改默认登录shell: $chsh ...
- 基于FPGA的DW8051移植(二)
基于上一篇博文继续,本来想换到oc8051,但是还是不甘心,弄了这么久还是没有弄出来,真是打击屎了. 上一篇说3f进入了operation code所以判断是代码错误,后来发现不可以这么判断. 因为地 ...
- 基于Sql Server 2008的分布式数据库的实践(四)
原文 基于Sql Server 2008的分布式数据库的实践(四) 数据库设计 1.E-R图 2.数据库创建 Win 7 1 create database V3 Win 2003 1 create ...
- 基于springmvc的简单增删改查实现---中间使用到了bean validation
package com.kite.controller; import java.util.HashMap; import java.util.Map; import javax.validation ...
- [转]如何申请和管理一个sourceforge项目
假如你没有贡献免费源代码的想法,就不用继续读本文了.:) 如果读者的e文不错,作者建议你直接阅读sourceforge的 howto文档,他们整理得非常周到详实.本文只是作者的使用经验,也许可以给与作 ...
- 《UNIX环境高级编程》笔记--sync、fsync和fdatasync函数
传统的UNIX实现在内核中设有缓冲区高速缓存或页面高速缓存,大多数磁盘 I/O都通过缓冲进行.当将数据写入文件时,内核通常先将该数据复制到其中一个缓冲区中,如果该缓冲区尚未写满,则并不将其排入输出队列 ...