js中的undefined探寻

背景

如果你了解Java,便知道类中未赋值的属性将在编译时由编译器赋予初始值。与Java、C#等一些静态语言不同的是,Javascript是一种解释型的动态语言,因为没有编译环节,因而它的变量类型可在程序运行时动态改变。这种弱类型的性质,也就决定了Javascript的设计中应该采用一种开放的、无意义的值作为变量的初始值——它便是undefined


探寻

undefined作为Javascripts的五种基本数据类型之一,在编程中也是很常见的了。比如所有未赋值的变量都会默认为undefined;未指明return语句的函数也会返回undefined;不存在的对象属性、不存在的数组项以及一些操作符等也会返回undefined,下面我们就来一同探寻undefined的踪迹。

变量

最常见的,未赋值的全局变量或局部变量将会返回undefined

var buzz;
buzz;                      // undefined,全局变量

(fucntion(arg) {
     var fizz;
     console.log(arg);     // undefined,参数变量
     console.log(fizz);    // undefined,局部变量
})();

函数

每个函数都有返回值,如果未指定return后的返回值,默认将返回undefined

var fn1 = function() {};
    fn2 = function() {return;}
var res1 = fn1();
    res2 = fn2();

console.log(res1);     // undefined,省略return
console.log(res2);     // undefined,未指定返回值

数组

访问数组中未定义数据项返回undefined

var arr = [1,2];
arr.length = 5;

console.log(arr[3]);      // undefined
console.log(arr[10]);     // undefined

对象

访问对象上的未定义属性返回undefined

var person = {
     name:"Lee",
};
person.age;     // undefined     

操作符

void操作符对后方表达式求值,不论求值结果如何,总是返回undefined

var res = void(1+1);
res;     // undefined

陷阱

尽管undefined的本意表示”缺少值”,本应有值,却还未定义。同时,JavaScript中的另一个基本类型变量之一null,也有”空引用、未定义”对象之意,初学者常常将两者混为一谈,稍不留意便会跌入陷阱。

undefined使用

对于undefined的判断,获取,转型需要牢记用法,若凭借其他语言的经验则容易发生意外结果。

判断undefined

可以使用=====typeof操作符判断undefined

var buzz;

buzz == undefined;             // true
buzz === undefined;            // true
buzz == 'undefined';           // false

typeof buzz == undefined;      // false
typeof buzz == 'undefined';    // true

当使用=====时与undefined基本类型值比较,使用typeof时与字符串比较。这么这几种判断方法真的都安全可靠吗,我们继续下面的例子:

(function() {
    var undefined = 'hello';
    var buzz;
    console.log(buzz == undefined);             // false
    console.log(buzz === undefined);            // false
    console.log(typeof buzz == 'undefined');    // true
})();

这是一个自调用函数,由于undefined在Javascript中不是保留字,因而我们可以在函数内重写undefined的值,至于原始值,只能从函数外部的全局作用域获取:

window.undefined;   // 浏览器环境
GLOBAL.undefined;   // Node环境

(function() {
    var undefined = 'hello';
    var buzz;
    console.log(undefined);                     // 'hello'
    console.log(buzz == window.undefined);      // true
    console.log(buzz === window.undefined);     // true
    console.log(typeof buzz == 'undefined');    // true
})();

总结以上结果,我们可以看到,使用typeof来判断undefined值,无论在什么情况下总会返回正确结果。为保障代码的健硕性,因而我们应始终使用typeof操作符来判断undefined

获取 undefined

通过原始字面量获取
var buzz = 'hello';
buzz = undefined;
buzz;     // undefined
通过void操作符获取

void操作符对后方表达式求值,不论求值结果如何,总是返回undefined。

var buzz = 'hello';
buzz = void 0;
typeof buzz === 'undefined';    // true
最佳实践

虽然通过原始字面量方式获取undefined简单方便,但在【判断undefined】这一小节中,我们曾提到:undefined不是Javascript中的保留字,其值可以在函数作用域内被改写。需要注意的是,即便是window/GLOBAL对象,在函数内也仍可被重写。故从window/GLOBAL上获取undefined并不是100%可靠的方法。如:

(function() { 
    var undefined = 'hello', 
        foo = {},
        window = { 
            'undefined': 'world'
        }; 
    console.log(undefined);              // 'hello'
    console.log(window.undefined);       // 'world'
    console.log(foo.a === undefined);    // false 
    console.log(foo.a === void 0);       // true 
})();

于是,采用void方式获取undefined便成了通用准则。如underscore.js里的isUndefined便是这么写的:

_.isUndefined = function(obj) {
    return obj === void 0;
}

还有一种方式是通过函数参数缺省值。如AngularJS的源码里就用这样的方式:

(function(window, document, undefined) {
    //.....
})(window, document);

undefined“参数通过省略传参,确保了其值是一个默认的undefined

undefined转型

undefinedNumber类型返回NaN,转String返回字符串形式,转Boolean返回false

// 显示转换
Number(undefined);         // NaN
String(undefined);         // 'undefined'
Boolean(undefined);        // false

// 隐式转换
1 + undefined;             // NaN,隐式转number
'str' + undefined;         // 'strundefined',隐式转string

if(undefined) {
    console.log(true);     // 不会被输出
} else {
    console.log(false);    // false,隐式转boolean
}

null

在Java,C#等一些面向对象语言中null代表空引用。当类中声明一个引用型变量未赋初值时,编译器会自动初始化引用值为null。JavaScript借鉴了这一设计,也将null定义为“空”,当一个变量值为null时代表它未引用任何对象实体。
对于null的典型用法是:

1. 作为函数的参数,表示该函数的参数不是对象。
2. 作为对象原型链的终点。

nullundefined在表现上有着一定的相似性,两者在if()语句中,都会被自动转为false,使用”==“运算符两者判定相等。

function choose(param) {
    if (param) {
        console.log(param + ' is true');
    } else {
        console.log(param + ' is false');
    }
}

choose(null);           // undefined is false
choose(undefined);      // null is false

undefined == null;      // true

虽然undefinednull在JavaScript中都可代表“空,未定义”的意思,但他们之间还是有一些细微的区别:

  1. null值需要显式指定,变量赋值为null时,代表一个对象,其引用实体为空。
  2. null转换为数值时返回0,undefined返回NaN
var foo = null;
typeof foo;     // 'object'
+ null;         // 0
+ undefined;    // NaN

总结

  • 使用typeof判断undefined
  • 使用void 0获取undefined
  • undefinednull转型为布尔值均返回false

拓展阅读

undefined与null的区别
谈谈Javascript中的void操作符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值