考虑到文章过长,不便于阅读,这里分出第二篇,如有后续,每15个知识点分为一篇...

第一篇地址:( 译、持续更新 ) JavaScript 上分小技巧(一)

第三篇地址:( 译、持续更新 ) JavaScript 上分小技巧(三)

第四篇地址:( 译、持续更新 ) JavaScript 上分小技巧(四)

#30 - 将true的/false的值转换成boolean类型
你可以通过!!操作将为true/为false的值转换为boolean类型。

!!"" // false
!!0 // false
!!null // false
!!undefined // false
!!NaN // false !!"hello" // true 字符串长度不为0时
!!1 // true
!!{} // true
!![] // true

### 2016-01-31 更新 ###

#29 - 使用缓存的记忆让递归函数加速运行
斐波那切数列(Fibonacci sequence)想必大家都不陌生(针对学霸而言,在这之前本兽完全不知道这是个什么鬼,虽然经常会用到递归),我们可以在20秒内写出以下的函数:

var fibonacci = function(n){
return n < 2 ? n : fibonacci(n-1) + fibonacci(n-2);
}

它确实是运行了,但是效率并不高。它做了大量的重复计算的工作,我们可以通过缓存先前计算结果的方法来加快速度。

var fibonacci = (function(){
var cache = {
0: 0,
1: 1
};
return function(n){
return n <= 1 ? cache[n] : (cache[n] = cache[n-1] + cache[n-2]);
}
})()

同时,我们可以定义一个高阶函数,该高阶函数将接收一个函数作为参数并且该参数函数会返回一个已记忆的缓存版本。

var memoize = function(func){
var cache = {};
return function(){
var key = Array.prototype.slice.call(arguments).toString();
return key in cache ? cache[key] : (cache[key] = func.apply(this,arguments));
}
}
fibonacci = memoize(fibonacci);

我们可以在很多情况下使用memoize()
GCD(最大公约数)

var gcd = memoize(function(a,b){
var t;
if (a < b) t=b, b=a, a=t;
while(b != 0) t=b, b = a%b, a=t;
return a;
})
gcd(27,183); //=> 3

阶乘计算

var factorial = memoize(function(n) {
return (n <= 1) ? 1 : n * factorial(n-1);
})
factorial(5); //=> 120

#28 - 柯里化(局部套用)和局部应用
柯里化(局部套用)
柯里化将以下函数

f:X*Y_-R

转换为以下形式的函数:

f':X_>(Y->R)

我们仅调用f'配合第一个参数,来代替配合两个参数来调用f。返回的结果是一个我们配合第二个参数调用的函数并且返回结果值的函数。
因此,如果我们调用未柯里化的函数f:

f(3,5)

然后调用柯里化的函数f':

f(3)(5)

案例:
未柯里化的add()

function add(x, y) {
return x + y;
}
add(3, 5); // _> 8

柯里化的add()

function addC(x) {
return function (y) {
return x + y;
}
}
addC(3)(5); // _> 8

柯里化的运算法则:
柯里化取一个二元函数,返回一个包含一元函数的一元函数。
柯里化:

(X × Y → R) → (X → (Y → R))

javascript 代码:

function curry(f) {
return function(x) {
return function(y) {
return f(x, y);
}
}
}

局部应用:
局部应用将以下函数

f:X*Y_-R

给定一个固定的值,传入一个参数,以此产生个新函数:

f':Y->R

f'和f不一样,但是他只需要填入第二个参数,这就是为什么f'比f的参数数量少一个。
案例:
绑定函数的第一个参数通过函数plus5进行与加5:

function plus5(y) {
return 5 + y;
}
plus5(3); // _> 8

局部应用的运算法则:
局部调用取一个二元函数和一个值,并且产生一个一元函数。
局部: ((X × Y → R) × X) → (Y → R)
javascript 代码:

function partApply(f, x) {
return function(y) {
return f(x, y);
}
}

### 2016-01-30 更新 ###

#27 - 简短语句
Short-circuit evaluation指出,仅当第一个参数的论据不足以确定表达式的值的时候才执行第二个参数:当第一个参数的AND(&&)函数返回false,整体value也将是false;当第一个参数的OR(||)为true,则整体的值也是true。
以下是test情况和isTrue函数和isFalse函数:

var test = true;
var isTrue = function(){
console.log('Test is true.');
};
var isFalse = function(){
console.log('Test is false.');
};

使用AND(&&)逻辑:

// 正常语句.
if(test){
isTrue(); // _> true
}
// 以上的功能使用 '&&' 完成
( test && isTrue() ); // _> true

使用OR(||)逻辑:

test = false;
if(!test){
isFalse(); // _> false.
}
( test || isFalse()); // _> false.

逻辑OR(||)语句同时可以用来给函数的参数设置默认值:

function theSameOldFoo(name){
name = name || 'Bar' ;
console.log("My best friend's name is " + name);
}
theSameOldFoo(); // My best friend's name is Bar
theSameOldFoo('Bhaskar'); // My best friend's name is Bhaskar

逻辑AND(&&)语句同时可以用来避免使用undefined的属性的例外,案例:

var dog = {
bark: function(){
console.log('Woof Woof');
}
};
// 调用 dog.bark();
dog.bark(); // Woof Woof.
//但是如果bog是undefined, dog.bark() 会抛出个错误 "Cannot read property 'bark' of undefined."
// 我们可以使用 && 来避免这种情况.
dog&&dog.bark(); // 这样的话,只有在bog存在的时候才会调用 dog.bark()

### 2016-01-28 更新 ###

#26 - 字符串列表的过滤和排序
你可能会有一个很大的字符串列表,你需要去对这个数组进行过滤和按字母排序。
在我们的例子中,我们将使用JavaScript来保存一系列的不同语言的关键字,但正如你所见,他们之间有重复,也没按字母顺序进行排序。所以这是一个完美的字符串列表(数组)来测试这个JavaScript小技巧。

var keywords = ['do', 'if', 'in', 'for', 'new', 'try', 'var', 'case', 'else', 'enum', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'delete', 'export', 'import', 'return', 'switch', 'typeof', 'default', 'extends', 'finally', 'continue', 'debugger', 'function', 'do', 'if', 'in', 'for', 'int', 'new', 'try', 'var', 'byte', 'case', 'char', 'else', 'enum', 'goto', 'long', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'final', 'float', 'short', 'super', 'throw', 'while', 'delete', 'double', 'export', 'import', 'native', 'public', 'return', 'static', 'switch', 'throws', 'typeof', 'boolean', 'default', 'extends', 'finally', 'package', 'private', 'abstract', 'continue', 'debugger', 'function', 'volatile', 'interface', 'protected', 'transient', 'implements', 'instanceof', 'synchronized', 'do', 'if', 'in', 'for', 'let', 'new', 'try', 'var', 'case', 'else', 'enum', 'eval', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'yield', 'delete', 'export', 'import', 'public', 'return', 'static', 'switch', 'typeof', 'default', 'extends', 'finally', 'package', 'private', 'continue', 'debugger', 'function', 'arguments', 'interface', 'protected', 'implements', 'instanceof', 'do', 'if', 'in', 'for', 'let', 'new', 'try', 'var', 'case', 'else', 'enum', 'eval', 'null', 'this', 'true', 'void', 'with', 'await', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'yield', 'delete', 'export', 'import', 'public', 'return', 'static', 'switch', 'typeof', 'default', 'extends', 'finally', 'package', 'private', 'continue', 'debugger', 'function', 'arguments', 'interface', 'protected', 'implements', 'instanceof'];

因为我们不打算改变原始列表,我们将使用一个名为filter的高阶函数,它会基于我们传递给它的函数进行过滤并且返回一个经过过滤的新数组。判断语句会将当前关键字的索引与新列表中的索引进行比较,如果索引能匹配上,则会将这项推到新的数组中。
最后,我们要使用排序功能以一个比较函数作为唯一的参数来对过滤后的列表进行排序,返回一个按字母顺序排序的列表。

var filteredAndSortedKeywords = keywords
.filter(function (keyword, index) {
return keywords.indexOf(keyword) === index;
})
.sort(function (a, b) {
if (a < b) return -1;
else if (a > b) return 1;
return 0;
});

ES6(ES 2015)使用arrow函数将会看上去简单些:

const filteredAndSortedKeywords = keywords
.filter((keyword, index) => keywords.indexOf(keyword) === index)
.sort((a, b) => {
if (a < b) return -1;
else if (a > b) return 1;
return 0;
});

这是进行过滤和排序后的关键字列表:

console.log(filteredAndSortedKeywords);
// ['abstract', 'arguments', 'await', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'double', 'else', 'enum', 'eval', 'export', 'extends', 'false', 'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import', 'in', 'instanceof', 'int', 'interface', 'let', 'long', 'native', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'super', 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var', 'void', 'volatile', 'while', 'with', 'yield']

### 2016-01-27 更新 ###

#25 - 使用立即执行函数表达式

被称为"Iffy"(IIFE-立即执行函数表达式)是一个在JavaScript中能够立即调用的匿名函数,并且还挺实用。

(function() {
// Do something
})()

用括号将匿名函数包裹起来,会将函数匿名函数转化成一个函数表达式或者变量表达式。因此,我们用一个未命名的函数表达式代替全局作用域下(或其他任何地方)的简单的匿名函数。

类似的,我们也可以为他创建一个名称,立即执行函数:

(someNamedFunction = function(msg) {
console.log(msg || "Nothing for today !!")
}) (); // 输出 -> Nothing for today !!
someNamedFunction("Javascript rocks !!"); // 输出 -> Javascript rocks !!
someNamedFunction(); // 输出 -> Nothing for today !!

更多的信息,点击以下的链接 link1 link2
演示:jsPerf

### 2016-01-26 更新 ###

#24 - 使用 === 代替 ==
==(或者!=)做对比的时候会将进行对比的两者转换到同一类型再比较。===(或者!==)则不会,他会将进行对比的两者做类型对比和值对比,相对于 == ,=== 的对比会更加严谨。

[10] == 10     // true
[10] === 10 // false
"10" == 10 // true
"10" === 10 // false
[] == 0 // true
[] === 0 // false
"" == false // true 但是 true == "a" 是false
"" === false // false

#23 - 转换数值的更快的方法
将字符串转换为数字是非常常见的。最简单和最快的(jspref)方式来实现,就是使用+(加)算法。

var one = '1';
var numberOne = +one; // Number 1

你也可以使用-(减号)算法的转换类型并且变成负数值。

var one = '1';
var negativeNumberOne = -one; // Number -1

#22 - 清空一个数组
你定义一个数组,并希望清空它的内容。通常,你会这样做:

var list = [1, 2, 3, 4];
function empty() {
//清空数组
list = [];
}
empty();

但是还有一种更高性能的方法。
你可以使用这些代码:

var list = [1, 2, 3, 4];
function empty() {
//清空数组
list.length = 0;
}
empty();

· list = [] 将一个变量指定个引用到那个数组,而其他引用都不受影响。这意味着,对于先前数组的内容的引用仍然保留在内存中,从而导致内存泄漏。
· list.length = 0 删除数组内的所有东西,这不需要引用任何其他的东西
然而,如果你有一个copy的数组(A和copy-A),如果你使用list.length = 0 删除其内容,副本也会失去它的内容。

var foo = [1,2,3];
var bar = [1,2,3];
var foo2 = foo;
var bar2 = bar;
foo = [];
bar.length = 0;
console.log(foo, bar, foo2, bar2);
//[] [] [1, 2, 3] []

StackOverflow上的更多详情:difference-between-array-length-0-and-array

#21 - 对数组排序进行"洗牌"(随机排序)
这段代码在这里使用Fisher Yates洗牌算法给一个指定的数组进行洗牌(随机排序)。

function shuffle(arr) {
var i,
j,
temp;
for (i = arr.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
};

案例:

var a = [1, 2, 3, 4, 5, 6, 7, 8];
var b = shuffle(a);
console.log(b);
// [2, 7, 8, 6, 5, 3, 1, 4]

网友@幻天芒在评论中提供的随机技巧:

arr.sort(function(){return Math.random() - 0.5;});

实测可用,感谢分享

#20 - 返回对象的函数能够用于链式操作
当创建面向对象的JavaScript对象的function时,函数返回一个对象将能够让函数可链式的写在一起来执行。

function Person(name) {
this.name = name;
this.sayName = function() {
console.log("Hello my name is: ", this.name);
return this;
};
this.changeName = function(name) {
this.name = name;
return this;
};
}
var person = new Person("John");
person.sayName().changeName("Timmy").sayName();
//Hello my name is: John
//Hello my name is: Timmy

#19 - 字符串安全连接
假设你有一些类型未知的变量,你想将它们连接起来。可以肯定的是,算法操作不会在级联时应用:

var one = 1;
var two = 2;
var three = '3';
var result = ''.concat(one, two, three); //"123"

这样的连接不正是你所期望的。相反,一些串联和相加可能会导致意想不到的结果:

var one = 1;
var two = 2;
var three = '3';
var result = one + two + three; //"33" 而不是 "123"

谈到性能,对join和concat进行比较,他们的执行速度是几乎一样的。你可以在MDN了解更多与concat相关的知识

#18 - 更快的四舍五入
今天的技巧是关于性能。见到过双波浪线"~~"操作符吗?它有时也被称为double NOT运算符。你可以更快的使用它来作为Math.floor()替代品。为什么呢?
单位移~将32位转换输入-(输入+1),因此双位移将输入转换为-(-(输入+1)),这是个趋于0的伟大的工具。对于输入的数字,它将模仿Math.ceil()取负值和Math.floor()取正值。如果执行失败,则返回0,这可能在用来代替Math.floor()失败时返回一个NaN的时候发挥作用。

// 单位移
console.log(~1337) // -1338
// 双位移
console.log(~~47.11) // -> 47
console.log(~~-12.88) // -> -12
console.log(~~1.9999) // -> 1
console.log(~~3) // -> 3
//失败的情况
console.log(~~[]) // -> 0
console.log(~~NaN) // -> 0
console.log(~~null) // -> 0
//大于32位整数则失败
console.log(~~(2147483647 + 1) === (2147483647 + 1)) // -> 0

虽然~~可能有更好的表现,为了可读性,请使用Math.floor()。

#17 - Node.js:让module在没被require的时候运行
在node里,你可以根据代是运行了require('./something.js')还是node something.js,来告诉你的程序去做两件不同的事情。如果你想与你的一个独立的模块进行交互,这是很有用的。

if (!module.parent) {
// 运行 `node something.js`
app.listen(8088, function() {
console.log('app listening on port 8088');
})
} else {
// 使用 `require('/.something.js')`
module.exports = app;
}

更多信息,请看the documentation for modules

#16 - 给回调函数传递参数
在默认情况下,你无法将参数传给回调函数,如下:

function callback() {
console.log('Hi human');
}
document.getElementById('someelem').addEventListener('click', callback);

你可以采取JavaScript闭包的优点来给回调函数传参,案例如下:

function callback(a, b) {
return function() {
console.log('sum = ', (a+b));
}
}
var x = 1, y = 2;
document.getElementById('someelem').addEventListener('click', callback(x, y));

什么是闭包呢?闭包是指一个针对独立的(自由)变量的函数。换句话说,闭包中定义的函数会记住它被创建的环境。了解更多请参阅MDN所以这种方式当被调用的时候,参数X/Y存在于回调函数的作用域内。
另一种方法是使用绑定方法。例如:

var alertText = function(text) {
alert(text);
};
document.getElementById('someelem').addEventListener('click', alertText.bind(this, 'hello'));

两种方法在性能上有一些略微区别,详情参阅jsperf

### 2016-01-25 更新 ###

( 译、持续更新 ) JavaScript 上分小技巧(二)的更多相关文章

  1. ( 译、持续更新 ) JavaScript 上分小技巧(四)

    后续如有内容,本篇将会照常更新并排满15个知识点,以下是其他几篇译文的地址: 第一篇地址:( 译.持续更新 ) JavaScript 上分小技巧(一) 第二篇地址:( 译.持续更新 ) JavaScr ...

  2. ( 译、持续更新 ) JavaScript 上分小技巧(三)

    最近家里杂事较多,自学时间实在少的可怜,所以都在空闲时间看看老外写的内容,学习之外顺便翻译分享~等学习的时间充足些再写写自己的一些学习内容和知识点分析(最近有在接触的:复习(C#,SQL).(学习)T ...

  3. ( 译、持续更新 ) JavaScript 上分小技巧(一)

    感谢好友破狼提供的这篇好文章,也感谢写这些知识点的作者们和将他们整理到一起的作者.这是github上的一篇文章,在这里本兽也就只做翻译,由于本兽英语水平和编程能力都不咋地,如有不好的地方也请多理解体谅 ...

  4. 文件上传小技巧/原生态【html篇】

    引语:大家都知道,html中上传文件就一个input,type=file就搞定了.但是,这个标签的样式,实在不值得提点什么,要改动他的样式,恐怕也是较难的.但是其实挺简单,今天就来说说上传文件小技巧吧 ...

  5. TypeScript和JavaScript的一些小技巧记录

    项目里使用到的技巧,记录一下,会持续更新. JS的技巧完全可以使用到TS上哦. JS 向下取整 Math.floor(4.5); 简写: var num = 4.5; ~~num; num <& ...

  6. 19个JavaScript简化编码小技巧

    这篇文章适合任何一位基于JavaScript开发的开发者.我写这篇文章主要涉及JavaScript中一些简写的代码,帮助大家更好理解一些JavaScript的基础.希望这些代码能从不同的角度帮助你更好 ...

  7. Javascript字符串拼接小技巧

    在Javascript中经常会遇到字符串的问题,但是如果要拼接的字符串过长就比较麻烦了. 如果是在一行的,可读性差不说,如果要换行的,会直接报错. 在此介绍几种Javascript拼接字符串的技巧. ...

  8. 一些有意思的面试题(持续更新) .C语言编程技巧札记

    一些有意思的面试题(持续更新) http://blog.csdn.net/wangyuling1234567890/article/details/38565239 C语言编程技巧札记 http:// ...

  9. 文件上传小技巧/后端处理【以php示例】

    引语:在上一篇文章中说到,在页面中可以用隐藏的方式让你的上传页面看起来漂亮.但是这对于性能来说,并没有什么卵用,那么在后台的处理中,难道就没有一些处理技巧么?所谓后台的技巧,应该要包括上传得快一点,上 ...

随机推荐

  1. 跟我学习Storm_Storm基本概念

    首先我们通过一个Storm和Hadoop的对比来了解Storm中的基本概念. 接下来我们再来具体看一下这些概念. Nimbus:负责资源分配和任务调度. Supervisor:负责接受nimbus分配 ...

  2. python中from module import * 的一个陷阱

    from module import *把module中的成员全部导到了当前的global namespace,访问起来就比较方便了.当然,python style一般不建议这么做,因为可能引起nam ...

  3. Nodejs基础:路径处理模块path总结

    模块概览 在nodejs中,path是个使用频率很高,但却让人又爱又恨的模块.部分因为文档说的不够清晰,部分因为接口的平台差异性. 将path的接口按照用途归类,仔细琢磨琢磨,也就没那么费解了. 获取 ...

  4. Scala函数式编程进阶

    package com.dtspark.scala.basics /** * 函数式编程进阶: * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量: * 2, 函数更长用的方式 ...

  5. css+div 浮动分块

    前段时间学过几天html,只是怀着了解的态度,能够读懂别人的页面,能够扒现成就行,一直没有自己动手去实践过,其实也不是没有实践过,前段时间扒了一个网页,想按照自己的要求来改,可后果是越改越乱.今天心血 ...

  6. Android开发自学笔记(Android Studio1.3.1)—1.环境搭建

    一.引言 .Google推出的 毫无疑问,这个是它的最大优势,Android Stuido是Google推出,专门为Android"量身订做"的,是Google大力支持的一款基于I ...

  7. Entity Framework与ADO.Net及NHibernate的比较

    Entity Framework  是微软推荐出.NET平台ORM开发组件, EF相对于ado.net 的优点 (1)开发效率高,Entity Framework的优势就是拥有更好的LINQ提供程序. ...

  8. Android开发之AutoCompleteTextView的简单使用

    这里只谈简单的使用: 代码xml: <AutoCompleteTextView android:id="@+id/actv" android:layout_width=&qu ...

  9. java/c# 判断点是否在多边形区域内

    java/c# 判断点是否在多边形区域内 年06月29日 ⁄ 综合 ⁄ 共 1547字 ⁄ 字号 小 中 大 ⁄ 评论关闭 最近帮别人解决了一个问题,如何判断一个坐标点,是否在多边形区域内(二维). ...

  10. mybatis执行批量更新batch update 的方法

    1.数据库连接必须配置:&allowMultiQueries=true 我的配置如下:jdbc:mysql://10.20.13.16:3306/CALENDAR?useUnicode=tru ...