本篇文章将会介绍和解析一些简单但是强大的JavaScript技巧. 这些技巧所有的JavaScript程序员都可以马上使用, 你不需要成为JavaScript高手才能理解这些.如果你还是新手, 而且读完所有这些技巧的详解和每种技巧是如果工作的以后运用它们, 你会写出更加简练高效的JavaScript程序.
强大的&&和||表达式
你可能在JavaScript库和JavaScript框架中已经见过它们了, 那么我们先由几个基本的例子开始:
Example 1:||
(或)
设置默认值,通常用:
function setKey(value){ if(!value){ value = "Default Value"; }}
用这个代替:
function setKey(value){ value = value || "Default Value";}
提示: JavaScript判断为假的值: null, false, 0, undefined, NaN和(空字符串). 记住像Infinity(无限大)这种 Number(感谢@xyzhanjiang 的指正) 的值是被判断为真不是假. 而NaN则被判断为假. 除了以上这些, 其他值全部被判断为真.
解析:- ||
操作符首先从左开始判断表达式的真假, 如果为真, 马上返回左边表达式返回的值; 如果左边表达式被判断为假, 则继续判断右边的表达式, 并返回右边表达式的值.- 如果value被判断为假, 会返回右边表达式的值. 换句话说, 如果value变量被判断为真, 则返回value的值.
Example 2:&&(并)
不要这么做:
function isAdult(age){ if(age && age > 17){ return true; }else{ return false; }}
用这个代替:
function isAdult(age){ return age && age > 17;}
解析:- &&
操作符从左开始判断表达式, 如果左边的表达式被判断为假, 则返回false(!注:如果左边表达式的值为0时,则返回0感谢@飞天鼠 的指正), 不管右边的表达式是否为真.- 如果左边的表达式为真, 则继续判断右边的表达式, 然后返回右边表达式结果.这变得越来越有趣了,不是吗?
Example 3:
不要这样做:
function checkLogin(userName){ if(userName){ logIn(userName); }else{ signUp(); }}
用这个代替:
function checkLogin(userName){ userName && logIn(userName) || signUp();}
解析:- 如果userName为真,则调用logIn函数并传递参数userName- 如果userName为假或者logIn
函数返回值为假(感谢@飞天鼠 的指正),则调用signUp
函数
Example 4:
不要这样做:
var user = {id:'this is id',log:'this is log'}, userId;if(user && user.log) { userId = user.id;}else{ userId = null;}
用这个代替:
var user = {id:'this is id',log:'this is log'}, userId;userId = user && user.log && user.id;
解析:- 如果user为真, 则调用user.log, 并检查user.log是否为真; 如果返回真, 则返回第三个表达式的返回值- 如果user为空, 返回null
下图为user.log存在的时候userId的值:
enter image description here
下图为user.log不存在的时候userId的值
enter image description here
强大的立即调用函数表达式
(什么是立即调用函数表达式, 何时使用它)IIFE(Immediately Invoked Function Expressions, 发音:"Iffy")是立即调用函数表达式的缩写形式, 它的语法大概如下:
(function () { // Do fun stuff})();
这是一个立即调用的匿名函数, 它在JavaScript中有一些特别重要的作用.
它是如何工作的?
包围匿名函数的一对括号会把它变成函数表达式
或者变量表达式
.
这就相当于:
// 不带括号:? = function () {};// 带括号:(? = function () {});// 函数被一个不知名的变量引用了, 一对括号把它包围了, 把它变成了一个匿名的函数表达式
同样的, 我们甚至可以创建一个命名的立即调用函数表达式:
(showName = function (name) {console.log(name || "No Name")}) (); // No NameshowName ("Rich"); // RichshowName (); // No Name
记住, 当你不用var
关键词创建变量的时候, JavaScript会自动判断该变量为全局变量
. 在上面的例子中是没有必要使用var
关键词的(因为你之后可能会调用它).
我们可以马上或者在这之后使用这个函数
但是我们不可以在之后调用匿名函数. 因为除非你创建匿名函数之后马上调用, 在这之后没有其他办法可以引用它. 这是匿名函数只可以马上调用它的原因.
当把匿名函数包含在一对括号里面时(字面量), 整个字面量会被运算,并且返回匿名函数的返回值. 它的返回值实质上是整个匿名函数自身, 所以我们只需要在这之后加上一对括号来马上调用它.
因此, 后面的一对括号等于告诉JavaScript编译器马上调用这个匿名函数, 所以它才会被称之为"立即调用函数表达式
".
因为JavaScript基于函数块的作用域规则, 在匿名函数内声明变量都是局部变量, 所以这些局部变量没办法直接从外部获取.
就像其他函数一样, 你可以向匿名函数设定参数和传递变量. 你可以根据这个特性, 利用匿名函数的作用域扩展它外围函数的作用域(即闭包).
什么时候应该使用它?
1.避免污染全局作用域IIFE
最广泛的用途是避免污染全局作用域. 已经有很多JavaScript库和JavaScript高手正在使用这种技巧, 尤其是在最流行jQuery插件的开发者中. 你也应该把这个技巧应用在你的程序的主要文件中(main.js).在这个例子中, 我使用了匿名函数把所有全局作用域的变量变成了局部变量, 所以现在全局作用域中还可以定义新的变量, 不用顾忌是否会和匿名函数内的变量在变量名上发生冲突(还包括其他库或者框架):
// 所有的代码包含在立即调用函数中(function () {
var firstName = “Richard”;
function init () {
doStuff (firstName); // 在这里开始插入应用程序的代码...
}
function doStuff () { // Do stuff here}function doMoreStuff () { // Do more stuff here}// 启动应用程序init ();
}) ();
2.用作条件选择器这种使用方式还没有被广泛所知, 但它是相当强大的. 你可以不调用一个命名函数来处理复杂的运算的. 注意在三目运算符(.. ? .. : ..
)中的两个匿名函数, 我尽可能多地加入空白来使语句看起来更容易理解:
var unnamedDocs = [], namedDocs = ["a_bridge_runover", "great_dreamers"];function createDoc(documentTitle) { var documentName = documentTitle ? (function (theName) { var newNamedDoc = theName.toLocaleLowerCase().replace(" ", ""); namedDocs.push(newNamedDoc); return newNamedDoc; })(documentTitle); : (function () { var newUnnamedDoc = "untitled" + Number(namedDocs.length + 1); unnamedDocs.push(newUnnamedDoc); return newUnnamedDoc; })(); return documentName;}createDoc("Over The Rainbow"); // over_the rainbowcreateDoc(); // untitled_4
网友评论