Previous Tip
+{{site.transl[page.lang].arrow_prev}}
{% endif %} - {% if page.next.url %} + {% if page.next.url and page.next.lang == page.lang %} -Next Tip
+{{site.transl[page.lang].arrow_next}}
{% endif %} {% endif %} @@ -81,7 +81,7 @@ {% if page.is_post %}-
-
- Home -
- About -
- Submit your tip! +
- {{site.transl[page.lang].menu.home.txt}} +
- {{site.transl[page.lang].menu.about.txt}} +
- {{site.transl[page.lang].menu.submit_your_tip.txt}}
-
Follow @tips_js
diff --git a/_layouts/home.html b/_layouts/home.html
index 72d0e0fd..8272a191 100644
--- a/_layouts/home.html
+++ b/_layouts/home.html
@@ -5,23 +5,21 @@
- - {% assign posts=paginator.posts | where:"lang", "es" %} - + {% assign posts=site.posts | where:"lang", page.lang | where:"type", posts %} {% for post in posts %}- {{ post.tipTlDt }} + {{ post.tip-tldr | markdownify }}{{item.name}}+} +... + +//good +
+``` +- [使用数组索引是一个坏习惯](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318#.76co046o9) +- `random()` 不会起作用 + +```javascript +//bad + +``` + +- 你可以创建以自己的唯一id。确定这个方法运行速度够快,把它附着到你的对象上。 +- 当子组件的数量很大或者包含重量级的组件时,使用key来提高性能。 +- [你必须提供key值给ReactCSSTransitionGroup的每个子组件](http://docs.reactjs-china.com/react/docs/animation.html) \ No newline at end of file diff --git a/_posts/zh_CN/2016-01-03-improve-nested-conditionals.md b/_posts/zh_CN/2016-01-03-improve-nested-conditionals.md new file mode 100644 index 00000000..54179ecb --- /dev/null +++ b/_posts/zh_CN/2016-01-03-improve-nested-conditionals.md @@ -0,0 +1,98 @@ +--- +layout: post + +title: 优化嵌套的条件语句 +tip-number: 03 +tip-username: AlbertoFuente +tip-username-profile: https://github.com/AlbertoFuente +tip-tldr: 我们怎样来提高和优化javascript里嵌套的`if`语句呢? + +categories: + - zh_CN +--- + + +我们怎样来提高和优化javascript里嵌套的`if`语句呢? + +```javascript +if (color) { + if (color === 'black') { + printBlackBackground(); + } else if (color === 'red') { + printRedBackground(); + } else if (color === 'blue') { + printBlueBackground(); + } else if (color === 'green') { + printGreenBackground(); + } else { + printYellowBackground(); + } +} +``` + + +一种方法来提高嵌套的`if`语句是用`switch`语句。虽然它不那么啰嗦而且排列整齐,但是并不建议使用它,因为这对于调试错误很困难。这告诉你[为什么](https://toddmotto.com/deprecating-the-switch-statement-for-object-literals/). + +```javascript +switch(color) { + case 'black': + printBlackBackground(); + break; + case 'red': + printRedBackground(); + break; + case 'blue': + printBlueBackground(); + break; + case 'green': + printGreenBackground(); + break; + default: + printYellowBackground(); +} +``` + + +但是如果在每个语句中都有很多条件检查时该怎么办呢?这种情况下,如果我们想要不罗嗦又整洁的话,我们可以用有条件的`switch`。如果我们传递`true`给`switch`语句,我们便可以在每个case中使用条件语句了。 + +```javascript +switch(true) { + case (typeof color === 'string' && color === 'black'): + printBlackBackground(); + break; + case (typeof color === 'string' && color === 'red'): + printRedBackground(); + break; + case (typeof color === 'string' && color === 'blue'): + printBlueBackground(); + break; + case (typeof color === 'string' && color === 'green'): + printGreenBackground(); + break; + case (typeof color === 'string' && color === 'yellow'): + printYellowBackground(); + break; +} +``` + + +但是我们应该时刻注意避免太多判断在一个条件里,尽量少的使用`switch`,考虑最有效率的方法:借助`object`。 + +```javascript +var colorObj = { + 'black': printBlackBackground, + 'red': printRedBackground, + 'blue': printBlueBackground, + 'green': printGreenBackground, + 'yellow': printYellowBackground +}; + + +if (color in colorObj) { + colorObj[color](); +} +``` + + +这里有更多相关的[内容](http://www.nicoespeon.com/en/2015/01/oop-revisited-switch-in-js/). + diff --git a/_posts/zh_CN/2016-01-04-sorting-strings-with-accented-characters.md b/_posts/zh_CN/2016-01-04-sorting-strings-with-accented-characters.md new file mode 100644 index 00000000..80137dde --- /dev/null +++ b/_posts/zh_CN/2016-01-04-sorting-strings-with-accented-characters.md @@ -0,0 +1,70 @@ +--- +layout: post + +title: 排列含音节字母的字符串 +tip-number: 04 +tip-username: loverajoel +tip-username-profile: https://github.com/loverajoel +tip-tldr: Javascript有一个原生方法**sort**可以排列数组。一次简单的`array.sort()`将每一个数组元素视为字符串并按照字母表排列。但是当你试图整理一个非ASCII元素的数组时,你可能会得到一个奇怪的结果。 + +categories: + - zh_CN +--- + +Javascript有一个原生方法**[sort](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)**可以排列数组。一次简单的`array.sort()`将每一个数组元素视为字符串并按照字母表排列。你也可以提供[自定义排列方法](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters)。 + +```javascript +['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort(); +// ["Buenos Aires", "Mumbai", "New York", "Shanghai"] +``` + + +但是当你试图整理一个如`['é', 'a', 'ú', 'c']`这样的非ASCII元素的数组时,你可能会得到一个奇怪的结果`['c', 'e', 'á', 'ú']`。这是因为排序方法只在英文下有用。 + +看一下下一个例子: + +```javascript +// 西班牙语 +['único','árbol', 'cosas', 'fútbol'].sort(); +// ["cosas", "fútbol", "árbol", "único"] // bad order + +// 德语 +['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(); +// ["Wann", "Woche", "wäre", "wöchentlich"] // bad order +``` + + +幸运的是,有两种方法可以解决这个问题,由ECMAScript国际化API提供的[localeCompare](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare)和[Intl.Collator](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Collator)。 + +> 两个方法都有自定义配置参数可以使其更好用。 + +### 使用`localeCompare()` + +```javascript +['único','árbol', 'cosas', 'fútbol'].sort(function (a, b) { + return a.localeCompare(b); +}); +// ["árbol", "cosas", "fútbol", "único"] + +['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(function (a, b) { + return a.localeCompare(b); +}); +// ["Wann", "wäre", "Woche", "wöchentlich"] +``` + + +### 使用`Intl.Collator()` + +```javascript +['único','árbol', 'cosas', 'fútbol'].sort(Intl.Collator().compare); +// ["árbol", "cosas", "fútbol", "único"] + +['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collator().compare); +// ["Wann", "wäre", "Woche", "wöchentlich"] +``` + + +- 两个方法都可以自定义区域位置。 +- 根据[Firefox](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Performance),当比较大数量的字符串时,使用`Intl.Collator`更快。 + +所以当你处理一个由非英语组成的字符串数组时,记得使用此方法来避免排序出现意外。 diff --git a/_posts/zh_CN/2016-01-05-differences-between-undefined-and-null.md b/_posts/zh_CN/2016-01-05-differences-between-undefined-and-null.md new file mode 100644 index 00000000..5356d313 --- /dev/null +++ b/_posts/zh_CN/2016-01-05-differences-between-undefined-and-null.md @@ -0,0 +1,43 @@ +--- +layout: post + +title: `undefined`与`null`的区别 +tip-number: 05 +tip-username: loverajoel +tip-username-profile: https://github.com/loverajoel +tip-tldr: 理解`undefined`与`null`的区别。 + +categories: + - zh_CN +--- + + +- `undefined`表示一个变量没有被声明,或者被声明了但没有被赋值 +- `null`是一个表示“没有值”的值 +- Javascript将未赋值的变量默认值设为`undefined` +- Javascript从来不会将变量设为`null`。它是用来让程序员表明某个用`var`声明的变量时没有值的。 +- `undefined`不是一个有效的JSON,而`null`是 +- `undefined`的类型(typeof)是`undefined` +- `null`的类型(typeof)是`object`. [为什么?](http://www.2ality.com/2013/10/typeof-null.html) +- 它们都是基本类型 +- 他们都是[falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) + (`Boolean(undefined) // false`, `Boolean(null) // false`) +- 你可以这样判断一个变量是否是[undefined](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/undefined) + + ```javascript + typeof variable === "undefined" +``` + +- 你可以这样判断一个变量是否是[null](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/null) + + ```javascript + variable === null +``` + +- **双等号**比较时它们相等,但**三等号**比较时不相等 + + ```javascript + null == undefined // true + + null === undefined // false +``` diff --git a/_posts/zh_CN/2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md b/_posts/zh_CN/2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md new file mode 100644 index 00000000..b5634dcc --- /dev/null +++ b/_posts/zh_CN/2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md @@ -0,0 +1,38 @@ +--- +layout: post + +title: 可以接受单参数与数组的方法 +tip-number: 06 +tip-username: mattfxyz +tip-username-profile: https://twitter.com/mattfxyz +tip-tldr: 写一个方法可以接受单个参数也可以接受一个数组,而不是分开写两个方法。这和jQuery的一些方法的工作原理很像(`css` 可以修改任何匹配到的选择器). + +categories: + - zh_CN +--- + +写一个方法可以接受单个参数也可以接受一个数组,而不是分开写两个方法。这和jQuery的一些方法的工作原理很像(`css` 可以修改任何匹配到的选择器). + +你只要把任何东西连接到一个数组. `Array.concat`可以接受一个数组也可以接受单个参数。 + +```javascript +function printUpperCase(words) { + var elements = [].concat(words); + for (var i = 0; i < elements.length; i++) { + console.log(elements[i].toUpperCase()); + } +} +``` + + +`printUpperCase`现在可以接受单个单词或多个单词的数组作为它的参数。 + +```javascript +printUpperCase("cactus"); +// => CACTUS +printUpperCase(["cactus", "bear", "potato"]); +// => CACTUS +// BEAR +// POTATO +``` + diff --git a/_posts/zh_CN/2016-01-07-use-strict-and-get-lazy.md b/_posts/zh_CN/2016-01-07-use-strict-and-get-lazy.md new file mode 100644 index 00000000..5665e6d8 --- /dev/null +++ b/_posts/zh_CN/2016-01-07-use-strict-and-get-lazy.md @@ -0,0 +1,65 @@ +--- +layout: post + +title: 使用"use strict" 变得懒惰 +tip-number: 07 +tip-username: nainslie +tip-username-profile: https://twitter.com/nat5an +tip-tldr: JavaScript的严格模式使开发者更容易写出“安全”的代码。 + +categories: + - zh_CN +--- + +(译者注:此片翻译较渣,欢迎指正,建议大家[阅读原文](http://www.jstips.co/en/use-strict-and-get-lazy/)或直接阅读[MDN对严格模式的中文介绍](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode) 并欢迎PR) + +JavaScript的严格模式使开发者更容易写出“安全”的代码。 + +通常情况下,JavaScript允许程序员相当粗心,比如你可以引用一个从未用"var"声明的变量。或许对于一个刚入门的开发者来说这看起来很方便,但这也是变量拼写错误或者从作用域外引用变量时引发的一系列错误的原因。 + +程序员喜欢电脑帮我们做一些无聊的工作,喜欢它自动的检查我们工作上的错误。这就是"use strict"帮我们做的,它把我们的错误转变为了JavaScript错误。 + +我们把这个指令放在js文件顶端来使用它: + +```javascript +// 全脚本严格模式 +"use strict"; +var v = "Hi! I'm a strict mode script!"; +``` + + +或者放在一个方法内: + +```javascript +function f() +{ + + // 方法级严格模式 + 'use strict'; + function nested() { return "And so am I!"; } + return "Hi! I'm a strict mode function! " + nested(); +} +function f2() { return "I'm not strict."; } +``` + + +通过在JavaScript文件或方法内引入此指令,使JavaScript引擎运行在严格模式下,这直接禁止了许多大项目中不受欢迎的操作。另外,严格模式也改变了以下行为: +* 只有被"var"声明过的变量才可以引用。 +* 试图写只读变量时将会报错 +* 只能通过"new"关键字调用构造方法 +* "this"不再隐式的指向全局变量 +* 对eval()有更严格的限制 +* 防止你使用预保留关键字命名变量 + +严格模式对于新项目来说是很棒的,但对于一些并没有使用它的老项目来说,引入它也是很有挑战性的。如果你把所有js文件都连接到一个大文件中的话,可能导致所有文件都运行在严格模式下,这可能也会有一些问题。 + +It is not a statement, but a literal expression, ignored by earlier versions of JavaScript. +严格模式的支持情况: +* Internet Explorer from version 10. +* Firefox from version 4. +* Chrome from version 13. +* Safari from version 5.1. +* Opera from version 12. + + +[MDN对严格模式的全面介绍](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode) diff --git a/_posts/zh_CN/2016-01-08-converting-a-node-list-to-an-array.md b/_posts/zh_CN/2016-01-08-converting-a-node-list-to-an-array.md new file mode 100644 index 00000000..119c7262 --- /dev/null +++ b/_posts/zh_CN/2016-01-08-converting-a-node-list-to-an-array.md @@ -0,0 +1,46 @@ +--- +layout: post + +title: 将Node List转换为数组(Array) +tip-number: 08 +tip-username: Tevko +tip-username-profile: https://twitter.com/tevko +tip-tldr: 这是一个快速、安全、可重用的方法将node list转换为DOM元素的数组。 + +categories: + - zh_CN +--- + +`querySelectorAll`方法返回一个类数组对象称为node list。这些数据结构被称为“类数组”,因为他们看似数组却没有类似`map`、`foreach`这样的数组方法。这是一个快速、安全、可重用的方法将node list转换为DOM元素的数组: + +```javascript +const nodelist = document.querySelectorAll('div'); +const nodelistToArray = Array.apply(null, nodelist); + + +//之后 .. + +nodelistToArray.forEach(...); +nodelistToArray.map(...); +nodelistToArray.slice(...); + + +//等... +``` + +`apply`方法可以在指定`this`时以数组形式向方法传递参数。[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)规定`apply`可以接受类数组对象,恰巧就是`querySelectorAll`方法所返回的内容。如果我们不需要指定方法内`this`的值时传`null`或`0`即可。返回的结果即包含所有数组方法的DOM元素数组。 + +如果你正在用ES2015你可以使用[展开运算符 `...`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_operator) + +```js +const nodelist = [...document.querySelectorAll('div')]; // 返回一个真正的数组 + +//之后 .. + +nodelist.forEach(...); +nodelist.map(...); +nodelist.slice(...); + + +//等... +``` diff --git a/_posts/zh_CN/2016-01-09-template-strings.md b/_posts/zh_CN/2016-01-09-template-strings.md new file mode 100644 index 00000000..c1093b1c --- /dev/null +++ b/_posts/zh_CN/2016-01-09-template-strings.md @@ -0,0 +1,39 @@ +--- +layout: post + +title: 模板字符串 +tip-number: 09 +tip-username: JakeRawr +tip-username-profile: https://github.com/JakeRawr +tip-tldr: ES6中,JS现在有了引号拼接字符串的替代品,模板字符串。 + +categories: + - zh_CN +--- + + +ES6中,JS现在有了引号拼接字符串的替代品,模板字符串。 + +示例: +普通字符串 +```javascript +var firstName = 'Jake'; +var lastName = 'Rawr'; +console.log('My name is ' + firstName + ' ' + lastName); +// My name is Jake Rawr +``` + +模板字符串 +```javascript +var firstName = 'Jake'; +var lastName = 'Rawr'; +console.log(`My name is ${firstName} ${lastName}`); +// My name is Jake Rawr +``` + + +在模板字符串中,你可以不用`\n`来生成多行字符串还可以在`${}`里做简单的逻辑运算(例如 2+3)。 + +你也可以使用方法修改模板字符串的输出内容;他们被称为[带标签的模板字符串](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/template_strings#Tagged_template_strings)(其中有带标签的模板字符串的示例) + +或许你还想[阅读更多内容](https://hacks.mozilla.org/2015/05/es6-in-depth-template-strings-2)来了解模板字符串。 diff --git a/_posts/zh_CN/2016-01-10-check-if-a-property-is-in-a-object.md b/_posts/zh_CN/2016-01-10-check-if-a-property-is-in-a-object.md new file mode 100644 index 00000000..0e128cc8 --- /dev/null +++ b/_posts/zh_CN/2016-01-10-check-if-a-property-is-in-a-object.md @@ -0,0 +1,64 @@ +--- +layout: post + +title: 检查某对象是否有某属性 +tip-number: 10 +tip-username: loverajoel +tip-username-profile: https://www.twitter.com/loverajoel +tip-tldr: 这是一些检查某对象是否有某属性的方法。 + +categories: + - zh_CN +--- + +当你需要检查某属性是否存在于一个[对象](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects),你可能会这样做: + +```javascript +var myObject = { + name: '@tips_js' +}; + + +if (myObject.name) { ... } + +``` + +这是可以的,但是你需要知道有两种原生方法可以解决此类问题。[`in` 操作符](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/in) 和 [`Object.hasOwnProperty`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty),任何继承自`Object`的对象都可以使用这两种方法。 + +### 看一下较大的区别 + +```javascript +var myObject = { + name: '@tips_js' +}; + +myObject.hasOwnProperty('name'); // true +'name' in myObject; // true + + +myObject.hasOwnProperty('valueOf'); // false, valueOf 继承自原型链 +'valueOf' in myObject; // true + +``` + + +两者检查属性的深度不同,换言之`hasOwnProperty`只在本身有此属性时返回true,而`in`操作符不区分属性来自于本身或继承自原型链。 + +这是另一个例子 + +```javascript +var myFunc = function() { + this.name = '@tips_js'; +}; +myFunc.prototype.age = '10 days'; + +var user = new myFunc(); + +user.hasOwnProperty('name'); // true + +user.hasOwnProperty('age'); // false, 因为age来自于原型链 +``` + +[在线示例](https://jsbin.com/tecoqa/edit?js,console)! + +同样建议阅读关于检查对象是否包含属性时常见错误的[讨论](https://github.com/loverajoel/jstips/issues/62)。 diff --git a/_posts/zh_CN/2016-01-11-hoisting.md b/_posts/zh_CN/2016-01-11-hoisting.md new file mode 100644 index 00000000..ba1c7de0 --- /dev/null +++ b/_posts/zh_CN/2016-01-11-hoisting.md @@ -0,0 +1,52 @@ +--- +layout: post + +title: 变量提升 +tip-number: 11 +tip-username: squizzleflip +tip-username-profile: https://twitter.com/squizzleflip +tip-tldr: JavaScript模块和构建步骤越来越复杂和多样化,但是新框架里的样板是什么样子的呢? + +categories: + - zh_CN +--- + +理解[变量提升](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/var#var_hoisting)可以帮助你组织方法作用域。只要记住变量生命和方法生命都会被提升到顶部。变量的定义不会提升,即使你在同一行声明和定义一个变量。变量**声明**是让系统知道有这个变量存在而**定义**是给其赋值。 + +```javascript +function doTheThing() { + // ReferenceError: notDeclared is not defined + console.log(notDeclared); + + // Outputs: undefined + console.log(definedLater); + var definedLater; + + definedLater = 'I am defined!' + // Outputs: 'I am defined!' + console.log(definedLater) + + // Outputs: undefined + console.log(definedSimulateneously); + var definedSimulateneously = 'I am defined!' + // Outputs: 'I am defined!' + console.log(definedSimulateneously) + + // Outputs: 'I did it!' + doSomethingElse(); + + function doSomethingElse(){ + console.log('I did it!'); + } + + // TypeError: undefined is not a function + functionVar(); + + var functionVar = function(){ + console.log('I did it!'); + } +} +``` + + +为了让你的代码更易读,将所有的变量声明在函数的顶端,这样可以更清楚的知道变量来自哪个作用域。在使用变量之前声明变量。将方法定义在函数的底部。 diff --git a/_posts/zh_CN/2016-01-12-pseudomandatory-parameters-in-es6-functions.md b/_posts/zh_CN/2016-01-12-pseudomandatory-parameters-in-es6-functions.md new file mode 100644 index 00000000..7ac58124 --- /dev/null +++ b/_posts/zh_CN/2016-01-12-pseudomandatory-parameters-in-es6-functions.md @@ -0,0 +1,29 @@ +--- +layout: post + +title: ES6中的伪强制参数 +tip-number: 12 +tip-username: Avraam Mavridis +tip-username-profile: https://github.com/AvraamMavridis +tip-tldr: 在许多编程语言中,方法的参数时默认强制需要的,开发人员需要明确定义一个可选的参数。 + +categories: + - zh_CN +--- + +在许多编程语言中,方法的参数时默认强制需要的,开发人员需要明确定义一个可选的参数。在Javascript中任何参数都是可选的,但是我们可以利用[**es6参数默认值**](http://exploringjs.com/es6/ch_parameter-handling.html#sec_parameter-default-values)特性的优点来实现强制要求这种表现而不污染本身的函数体。 + +```javascript +const _err = function( message ){ + throw new Error( message ); +} + +const getSum = (a = _err('a is not defined'), b = _err('b is not defined')) => a + b + +getSum( 10 ) // throws Error, b is not defined +getSum( undefined, 10 ) // throws Error, a is not defined + ``` + + + + `_err`方法会立即抛出一个错误。如果没有传递值给参数,默认值将会被使用, `_err`方法将被调用而错误也将被抛出。你可以从[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Default_parameters)看到更多关于**默认参数特性**的例子。 diff --git a/_posts/zh_CN/2016-01-13-tip-to-measure-performance-of-a-javascript-block.md b/_posts/zh_CN/2016-01-13-tip-to-measure-performance-of-a-javascript-block.md new file mode 100644 index 00000000..fbe12696 --- /dev/null +++ b/_posts/zh_CN/2016-01-13-tip-to-measure-performance-of-a-javascript-block.md @@ -0,0 +1,37 @@ +--- +layout: post + +title: 测量javascript代码块性能的小知识 +tip-number: 13 +tip-username: manmadareddy +tip-username-profile: https://twitter.com/manmadareddy +tip-tldr: 快速的测量javascript的性能,我们可以使用console的方法,例如 +```console.time(label)```和 ```console.timeEnd(label)``` + +categories: + - zh_CN +--- + +快速的测量javascript的性能,我们可以使用console的方法,例如 +[```console.time(label)```](https://developer.chrome.com/devtools/docs/console-api#consoletimelabel) 和 [```console.timeEnd(label)```](https://developer.chrome.com/devtools/docs/console-api#consoletimeendlabel) + + +```javascript +console.time("Array initialize"); +var arr = new Array(100), + len = arr.length, + i; + +for (i = 0; i < len; i++) { + arr[i] = new Object(); +}; +console.timeEnd("Array initialize"); // Outputs: Array initialize: 0.711ms +``` + + +更多内容: +[Console object](https://github.com/DeveloperToolsWG/console-object), +[Javascript benchmarking](https://mathiasbynens.be/notes/javascript-benchmarking) + +Demo: [jsfiddle](https://jsfiddle.net/meottb62/) - [codepen](http://codepen.io/anon/pen/JGJPoa) (在浏览器控制台输出) + diff --git a/_posts/zh_CN/2016-01-14-fat-arrow-functions.md b/_posts/zh_CN/2016-01-14-fat-arrow-functions.md new file mode 100644 index 00000000..809ad7a5 --- /dev/null +++ b/_posts/zh_CN/2016-01-14-fat-arrow-functions.md @@ -0,0 +1,104 @@ +--- +layout: post + +title: 箭头函数 +tip-number: 14 +tip-username: pklinger +tip-username-profile: https://github.com/pklinger/ +tip-tldr: 介绍一个ES6的新特性,箭头函数或许一个让你用更少行写更多代码的方便工具。 + +categories: + - zh_CN +--- + + +介绍一个ES6的新特性,箭头函数或许一个让你用更少行写更多代码的方便工具。它的名字(fat arrow functions)来自于它的语法`=>`是一个比瘦箭头`->`要'胖的箭头'(译者注:但是国内貌似不分胖瘦就叫箭头函数)。Some programmers might already know this type of functions from different languages such as Haskell as 'lambda expressions' respectively 'anonymous functions'. It is called anonymous, as these arrow functions do not have a descriptive function name.(译者注:一些其他语言中的箭头函数,避免不准确就不翻译了 欢迎PR) + +### 有什么益处呢? +* 语法: 更少的代码行; 不再需要一遍一遍的打`function`了 +* 语义: 从上下文中捕获`this`关键字 + +### 简单的语法示例 +观察一下这两个功能完全相同的代码片段。你将很快明白箭头函数做了什么。 + +```javascript +// 箭头函数的一般语法 +param => expression + +// 也可以用用小括号 +// 多参数时小括号是必须的 +(param1 [, param2]) => expression + + +// 使用functions +var arr = [5,3,2,9,1]; +var arrFunc = arr.map(function(x) { + return x * x; +}); +console.log(arr) + +// 使用箭头函数 +var arr = [5,3,2,9,1]; +var arrFunc = arr.map((x) => x*x); +console.log(arr) +``` + +正如你所看到的,箭头函数在这种情况下省去了写小括号,function以及return的时间。我建议你总是使用小括号,因为对于像`(x,y) => x+y`这样多参数函数,小括号总是需要的。这仅是以防在不同使用场景下忘记小括号的一种方法。但是上面的代码和`x => x*x`是一样的。至此仅是语法上的提升,减少了代码行数并提高了可读性。 + +### Lexically binding `this` + +这是另一个使用箭头函数的好原因。这是一个关于`this`上下文的问题。使用箭头函数,你不需要再担心`.bind(this)`也不用再设置`that = this`了,因为箭头函数继承了外围作用域的`this`值。看一下下面的[示例](https://jsfiddle.net/pklinger/rw94oc11/): + +```javascript + +// 全局定义 this.i +this.i = 100; + +var counterA = new CounterA(); +var counterB = new CounterB(); +var counterC = new CounterC(); +var counterD = new CounterD(); + +// 不好的例子 +function CounterA() { + // CounterA的`this`实例 (!!调用时忽略了此实例) + this.i = 0; + setInterval(function () { + // `this` 指向全局(global)对象,而不是CounterA的`this` + // 所以从100开始计数,而不是0 (本地的this.i) + this.i++; + document.getElementById("counterA").innerHTML = this.i; + }, 500); +} + +// 手动绑定 that = this +function CounterB() { + this.i = 0; + var that = this; + setInterval(function() { + that.i++; + document.getElementById("counterB").innerHTML = that.i; + }, 500); +} + +// 使用 .bind(this) +function CounterC() { + this.i = 0; + setInterval(function() { + this.i++; + document.getElementById("counterC").innerHTML = this.i; + }.bind(this), 500); +} + +// 箭头函数 +function CounterD() { + this.i = 0; + setInterval(() => { + this.i++; + document.getElementById("counterD").innerHTML = this.i; + }, 500); +} +``` + +更多有关箭头函数的内容可以查看[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions)。更多语法选项请看[这里](http://jsrocks.org/2014/10/arrow-functions-and-their-scope/). + diff --git a/_posts/zh_CN/2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md b/_posts/zh_CN/2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md new file mode 100644 index 00000000..49c919b6 --- /dev/null +++ b/_posts/zh_CN/2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md @@ -0,0 +1,79 @@ +--- +layout: post + +title: 更简单的使用indexOf实现contains功能 +tip-number: 15 +tip-username: jhogoforbroke +tip-username-profile: https://twitter.com/jhogoforbroke +tip-tldr: JavaScript并未提供contains方法。检测子字符串是否存在于字符串或者变量是否存在于数组你可能会这样做。 + +categories: + - zh_CN +--- + + +JavaScript并未提供contains方法。检测子字符串是否存在于字符串或者变量是否存在于数组你可能会这样做: + +```javascript +var someText = 'javascript rules'; +if (someText.indexOf('javascript') !== -1) { +} + +// or +if (someText.indexOf('javascript') >= 0) { +} +``` + +但是让我们看一下这些 [Expressjs](https://github.com/strongloop/express)代码段。 + +[examples/mvc/lib/boot.js](https://github.com/strongloop/express/blob/2f8ac6726fa20ab5b4a05c112c886752868ac8ce/examples/mvc/lib/boot.js#L26) +```javascript +for (var key in obj) { + // "reserved" exports + if (~['name', 'prefix', 'engine', 'before'].indexOf(key)) continue; +``` + +[lib/utils.js](https://github.com/strongloop/express/blob/2f8ac6726fa20ab5b4a05c112c886752868ac8ce/lib/utils.js#L93) +```javascript +exports.normalizeType = function(type){ + return ~type.indexOf('/') + ? acceptParams(type) + : { value: mime.lookup(type), params: {} }; +}; +``` + +[examples/web-service/index.js](https://github.com/strongloop/express/blob/2f8ac6726fa20ab5b4a05c112c886752868ac8ce/examples/web-service/index.js#L35) +```javascript +// key is invalid +if (!~apiKeys.indexOf(key)) return next(error(401, 'invalid api key')); +``` + +难点是 [位操作符](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) **~**, “按位操作符操作数字的二进制形式,但是返回值依然是标准的JavaScript数值。” + +它将`-1`转换为`0`,而`0`在javascript为`false`,所以: + +```javascript +var someText = 'text'; +!!~someText.indexOf('tex'); // someText contains "tex" - true +!~someText.indexOf('tex'); // someText NOT contains "tex" - false +~someText.indexOf('asd'); // someText doesn't contain "asd" - false +~someText.indexOf('ext'); // someText contains "ext" - true +``` + +### String.prototype.includes() + +在ES6中提供了[includes() 方法](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/includes)供我们判断一个字符串是否包含了另一个字符串: + +```javascript +'something'.includes('thing'); // true +``` + +在ECMAScript 2016 (ES7)甚至可能将其应用于数组,像indexOf一样: + +```javascript +!!~[1, 2, 3].indexOf(1); // true +[1, 2, 3].includes(1); // true +``` + +**不幸的是, 只有Chrome、Firefox、Safari 9及其更高版本和Edge支持了这功能。IE11及其更低版本并不支持** +**最好在受控的环境中使用此功能** diff --git a/_posts/zh_CN/2016-01-16-passing-arguments-to-callback-functions.md b/_posts/zh_CN/2016-01-16-passing-arguments-to-callback-functions.md new file mode 100644 index 00000000..211ce681 --- /dev/null +++ b/_posts/zh_CN/2016-01-16-passing-arguments-to-callback-functions.md @@ -0,0 +1,47 @@ +--- +layout: post + +title: 向回调方法传递参数 +tip-number: 16 +tip-username: minhazav +tip-username-profile: https://twitter.com/minhazav +tip-tldr: JavaScript modules and build steps are getting more numerous and complicated, but what about boilerplate in new frameworks? + +categories: + - zh_CN +--- + +通常下,你并不能给回调函数传递参数。 比如: +```js +function callback() { + console.log('Hi human'); +} + +document.getElementById('someelem').addEventListener('click', callback); +``` +你可以借助Javascript闭包的优势来传递参数给回调函数。看这个例子: +```js +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的文档](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures)。 + +这种方法使参数`x`和`y`在回调方法被调用时处于其作用域内。 + +另一个办法是使用`bind`方法。比如: +```js +var alertText = function(text) { + alert(text); +}; + +document.getElementById('someelem').addEventListener('click', alertText.bind(this, 'hello')); +``` +两种方法之间有着微小的性能差异,请看[jsperf](http://jsperf.com/bind-vs-closure-23). diff --git a/_posts/zh_CN/2016-01-17-nodejs-run-a-module-if-it-is-not-required.md b/_posts/zh_CN/2016-01-17-nodejs-run-a-module-if-it-is-not-required.md new file mode 100644 index 00000000..817e86e3 --- /dev/null +++ b/_posts/zh_CN/2016-01-17-nodejs-run-a-module-if-it-is-not-required.md @@ -0,0 +1,28 @@ +--- +layout: post + +title: Node.js - 运行未被引用的模块 +tip-number: 17 +tip-username: odsdq +tip-username-profile: https://twitter.com/odsdq +tip-tldr: 在Node里,你可以让你的程序根据其运行自`require('./something.js')`或者`node something.js`而做不同的处理。如果你想与你的一个独立的模块进行交互,这是非常有用的。 + +categories: + - zh_CN +--- + +在Node里,你可以让你的程序根据其运行自`require('./something.js')`或者`node something.js`而做不同的处理。如果你想与你的一个独立的模块进行交互,这是非常有用的。 + +```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; +} +``` + +更多内容请看 [modules的文档](https://nodejs.org/api/modules.html#modules_module_parent) diff --git a/_posts/zh_CN/2016-01-18-rounding-the-fast-way.md b/_posts/zh_CN/2016-01-18-rounding-the-fast-way.md new file mode 100644 index 00000000..e45a0bc4 --- /dev/null +++ b/_posts/zh_CN/2016-01-18-rounding-the-fast-way.md @@ -0,0 +1,37 @@ +--- +layout: post + +title: 更快的取整 +tip-number: 18 +tip-username: pklinger +tip-username-profile: https://github.com/pklinger +tip-tldr: 今天的小知识有关性能表现。曾经用过双波浪`~~` 操作符吗? 有时候也称为双非(NOT)位操作. 你可以用它作为`Math.floor()`的替代方法。为什么会这样呢? + +categories: + - zh_CN +--- + +今天的小知识有关性能表现。[曾经用过双波浪](http://stackoverflow.com/questions/5971645/what-is-the-double-tilde-operator-in-javascript) `~~` 操作符吗? 有时候也称为双非(NOT)位操作. 你可以用它作为`Math.floor()`的替代方法。为什么会这样呢? + +一个位操作符 `~` 将输入的32位的数字(input)转换为 `-(input+1)`. 两个位操作符将输入(input)转变为 `-(-(input + 1)+1)` 是一个使结果趋向于0的取整好工具. 对于数字, 负数就像使用`Math.ceil()`方法而正数就像使用`Math.floor()`方法. 转换失败时,返回`0`,这在`Math.floor()`方法转换失败返回`NaN`时或许会派上用场。 + +```javascript +// 单个 ~ +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()`. diff --git a/_posts/zh_CN/2016-01-19-safe-string-concatenation.md b/_posts/zh_CN/2016-01-19-safe-string-concatenation.md new file mode 100644 index 00000000..12a6b3ee --- /dev/null +++ b/_posts/zh_CN/2016-01-19-safe-string-concatenation.md @@ -0,0 +1,37 @@ +--- +layout: post + +title: 安全的字符串拼接 +tip-number: 19 +tip-username: gogainda +tip-username-profile: https://twitter.com/gogainda +tip-tldr: +假如你需要拼接一些不确定类型的变量为字符串,你需要确保算术运算符在你拼接时不会起作用。使用concat + +categories: + - zh_CN +--- + +假如你需要拼接一些不确定类型的变量为字符串,你需要确保算术运算符在你拼接时不会起作用。使用concat: + +```javascript +var one = 1; +var two = 2; +var three = '3'; + +var result = ''.concat(one, two, three); //"123" +``` + +这应该就是你所期望的拼接结果。如果不这样,拼接时加号可能会导致你意想不到的结果: + +```javascript +var one = 1; +var two = 2; +var three = '3'; + +var result = one + two + three; //"33" instead of "123" +``` + +关于性能,与用[```join```](http://www.sitepoint.com/javascript-fast-string-concatenation/)来拼接字符串相比 ```concat```的效率是几乎一样的。 + +你可以在[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)了解更多关于```concat```方法的内容。 diff --git a/_posts/zh_CN/2016-01-20-return-objects-to-enable-chaining-of-functions.md b/_posts/zh_CN/2016-01-20-return-objects-to-enable-chaining-of-functions.md new file mode 100644 index 00000000..5cd71bb3 --- /dev/null +++ b/_posts/zh_CN/2016-01-20-return-objects-to-enable-chaining-of-functions.md @@ -0,0 +1,33 @@ +--- +layout: post + +title: 返回对象,使方法可以链式调用 +tip-number: 20 +tip-username: WakeskaterX +tip-username-profile: https://twitter.com/WakeStudio +tip-tldr: 在面向对象的Javascript中为对象建立一个方法时,返回当前对象可以让你在一条链上调用方法。 + +categories: + - zh_CN +--- + +在面向对象的Javascript中为对象建立一个方法时,返回当前对象可以让你在一条链上调用方法。 + +```js +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(); +``` diff --git a/_posts/zh_CN/2016-01-21-shuffle-an-array.md b/_posts/zh_CN/2016-01-21-shuffle-an-array.md new file mode 100644 index 00000000..2a0c5917 --- /dev/null +++ b/_posts/zh_CN/2016-01-21-shuffle-an-array.md @@ -0,0 +1,38 @@ +--- +layout: post + +title: 对数组洗牌 +tip-number: 21 +tip-username: 0xmtn +tip-username-profile: https://github.com/0xmtn/ +tip-tldr: `Fisher-Yates Shuffling`算法对数组进行洗牌 + +categories: + - zh_CN +--- + + + 这段代码运用了[Fisher-Yates Shuffling](https://www.wikiwand.com/en/Fisher%E2%80%93Yates_shuffle)算法对数组进行洗牌。 + +```javascript +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; +}; +``` +调用示例: + +```javascript +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] +``` diff --git a/_posts/zh_CN/2016-01-22-two-ways-to-empty-an-array.md b/_posts/zh_CN/2016-01-22-two-ways-to-empty-an-array.md new file mode 100644 index 00000000..f076fff7 --- /dev/null +++ b/_posts/zh_CN/2016-01-22-two-ways-to-empty-an-array.md @@ -0,0 +1,57 @@ +--- +layout: post + +title: 清空数组的两种方法 +tip-number: 22 +tip-username: microlv +tip-username-profile: https://github.com/microlv +tip-tldr: 在JavaScript中清空一个数组有很多方法,但这是一个最高效的方法。 + +categories: + - zh_CN +--- + +如果你定义了一个数组,然后你想清空它。 +通常,你会这样做: + +```javascript +// 定义一个数组 +var list = [1, 2, 3, 4]; +function empty() { + //清空数组 + list = []; +} +empty(); +``` +但是,这有一个效率更高的方法来清空数组。 +你可以这样写: +```javascript +var list = [1, 2, 3, 4]; +function empty() { + //empty your array + list.length = 0; +} +empty(); +``` +* `list = []` 将一个新的数组的引用赋值给变量,其他引用并不受影响。 +这意味着以前数组的内容被引用的话将依旧存在于内存中,这将导致内存泄漏。 + +* `list.length = 0` 删除数组里的所有内容,也将影响到其他引用。 + +然而,如果你复制了一个数组(A 和 Copy-A),如果你用`list.length = 0`清空了它的内容,复制的数组也会清空它的内容。 + +考虑一下将会输出什么: +```js +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](http://stackoverflow.com/questions/4804235/difference-between-array-length-0-and-array) + diff --git a/_posts/zh_CN/2016-01-23-converting-to-number-fast-way.md b/_posts/zh_CN/2016-01-23-converting-to-number-fast-way.md new file mode 100644 index 00000000..0d0aaff1 --- /dev/null +++ b/_posts/zh_CN/2016-01-23-converting-to-number-fast-way.md @@ -0,0 +1,28 @@ +--- +layout: post + +title: 转换为数字的更快方法 +tip-number: 23 +tip-username: sonnyt +tip-username-profile: http://twitter.com/sonnyt +tip-tldr: 将字符串转换为数字是极为常见的。最简单和快速的方法是使用`+`(加号) 来实现。 + +categories: + - zh_CN +--- + +将字符串转换为数字是极为常见的。最简单和快速的方法([jsPref](https://jsperf.com/number-vs-parseint-vs-plus/29))`+`(加号) 来实现。 + +```javascript +var one = '1'; + +var numberOne = +one; // Number 1 +``` + +你也可以用`-`(减号)将其转化为负数值。 + +```javascript +var one = '1'; + +var negativeNumberOne = -one; // Number -1 +``` diff --git a/_posts/zh_CN/2016-01-24-use_===_instead_of_==.md b/_posts/zh_CN/2016-01-24-use_===_instead_of_==.md new file mode 100644 index 00000000..80c86551 --- /dev/null +++ b/_posts/zh_CN/2016-01-24-use_===_instead_of_==.md @@ -0,0 +1,29 @@ +--- +layout: post + +title: 使用 === 而不是 == +tip-number: 24 +tip-username: bhaskarmelkani +tip-username-profile: https://www.twitter.com/bhaskarmelkani +tip-tldr: `==` (或者 `!=`) 操作在需要的情况下自动进行了类型转换。`===` (或 `!==`)操作不会执行任何转换。`===`在比较值和类型时,可以说比`==`更快([jsPref](http://jsperf.com/strictcompare))。 + +categories: + - zh_CN +--- + +`==` (或者 `!=`) 操作在需要的情况下自动进行了类型转换。`===` (或 `!==`)操作不会执行任何转换。`===`在比较值和类型时,可以说比`==`更快([jsPref](http://jsperf.com/strictcompare))。 + +```js +[10] == 10 // 为 true +[10] === 10 // 为 false + +'10' == 10 // 为 true +'10' === 10 // 为 false + + [] == 0 // 为 true + [] === 0 // 为 false + + '' == false // 为 true 但 true == "a" 为false + '' === false // 为 false + +``` diff --git a/_posts/zh_CN/2016-01-25-Using-immediately-invoked-function-expression.md b/_posts/zh_CN/2016-01-25-Using-immediately-invoked-function-expression.md new file mode 100644 index 00000000..a33e4cda --- /dev/null +++ b/_posts/zh_CN/2016-01-25-Using-immediately-invoked-function-expression.md @@ -0,0 +1,46 @@ +--- +layout: post + +title: 使用立即执行函数表达式 +tip-number: 25 +tip-username: rishantagarwal +tip-username-profile: https://github.com/rishantagarwal +tip-tldr: 立即执行函数表达式( IIFE - immediately invoked function expression)是一个立即执行的匿名函数表达式,它在Javascript中有一些很重要的用途。 + + +categories: + - zh_CN +--- + +立即执行函数表达式( IIFE - immediately invoked function expression)是一个立即执行的匿名函数表达式,它在Javascript中有一些很重要的用途。 + +```javascript + +(function() { + // Do something + } +)() + +``` + +这是一个立即执行的匿名函数表达式,它在有JavaScript一些特别重要的用途。 + +两对括号包裹着一个匿名函数,使匿名函数变成了一个函数表达式。于是,我们现在拥有了一个未命名的函数表达式,而不是一个全局作用域下或在任何地方定义的的简单函数。 + +类似地,我们也可以创建一个命名过的立即执行函数表达式: + +```javascript +(someNamedFunction = function(msg) { + console.log(msg || "Nothing for today !!") + }) (); // 输出 --> Nothing for today !! + +someNamedFunction("Javascript rocks !!"); // 输出 --> Javascript rocks !! +someNamedFunction(); // 输出 --> Nothing for today !! +``` + +更多内容, 请参考下面链接 - +1. [链接 1](https://blog.mariusschulz.com/2016/01/13/disassembling-javascripts-iife-syntax) +2. [链接 2](http://javascriptissexy.com/12-simple-yet-powerful-javascript-tips/) + +效率: +[jsPerf](http://jsperf.com/iife-with-call) \ No newline at end of file diff --git a/_posts/zh_CN/2016-01-26-filtering-and-sorting-a-list-of-strings.md b/_posts/zh_CN/2016-01-26-filtering-and-sorting-a-list-of-strings.md new file mode 100644 index 00000000..2e91d9f0 --- /dev/null +++ b/_posts/zh_CN/2016-01-26-filtering-and-sorting-a-list-of-strings.md @@ -0,0 +1,56 @@ +--- +layout: post + +title: 过滤并排序字符串列表 +tip-number: 26 +tip-username: davegomez +tip-username-profile: https://github.com/davegomez +tip-tldr: 你可能有一个很多名字组成的列表,需要过滤掉重复的名字并按字母表将其排序。 + +categories: + - zh_CN +--- + +你可能有一个很多名字组成的列表,需要过滤掉重复的名字并按字母表将其排序。 + +在我们的例子里准备用不同版本语言的**JavaScript 保留字**的列表,但是你能发现,有很多重复的关键字而且它们并没有按字母表顺序排列。所以这是一个完美的字符串列表([数组](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array))来测试我们的JavaScript小知识。 + +```js +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`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter),它将基于我们传递的回调方法返回一个新的过滤后的数组。回调方法将比较当前关键字在原始列表里的索引和新列表中的索引,仅当索引匹配时将当前关键字push到新数组。 + +最后我们准备使用[`sort`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)方法排序过滤后的列表,`sort`只接受一个比较方法作为参数,并返回按字母表排序后的列表。 + +```js +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** (ECMAScript 2015)版本下使用[箭头函数](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions)看起来更简单: + +```js +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; + }); +``` + +这是最后过滤和排序后的JavaScript保留字列表: + +```js +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'] +``` diff --git a/_posts/zh_CN/2016-01-27-short-circiut-evaluation-in-js.md b/_posts/zh_CN/2016-01-27-short-circiut-evaluation-in-js.md new file mode 100644 index 00000000..83df2329 --- /dev/null +++ b/_posts/zh_CN/2016-01-27-short-circiut-evaluation-in-js.md @@ -0,0 +1,78 @@ +--- +layout: post + +title: JS中的短路求值 +tip-number: 27 +tip-username: bhaskarmelkani +tip-username-profile: https://www.twitter.com/bhaskarmelkani +tip-tldr: 短路求值是说, 只有当第一个运算数的值无法确定逻辑运算的结果时,才对第二个运算数进行求值:当AND(`&&`)的第一个运算数的值为false时,其结果必定为false;当OR(`||`)的第一个运算数为true时,最后结果必定为true。 + +categories: + - zh_CN +--- + +[短路求值](https://zh.wikipedia.org/wiki/%E7%9F%AD%E8%B7%AF%E6%B1%82%E5%80%BC)是说, 只有当第一个运算数的值无法确定逻辑运算的结果时,才对第二个运算数进行求值:当AND(`&&`)的第一个运算数的值为false时,其结果必定为false;当OR(`||`)的第一个运算数为true时,最后结果必定为true。 + +对于下面的`test`条件和`isTrue`与`isFalse`方法 + +```js +var test = true; +var isTrue = function(){ + console.log('Test is true.'); +}; +var isFalse = function(){ + console.log('Test is false.'); +}; + +``` +使用逻辑与 - `&&`. + +```js +// 普通的if语句 +if(test){ + isTrue(); // Test is true +} + +// 上面的语句可以使用 '&&' 写为: + +( test && isTrue() ); // Test is true +``` +使用逻辑或 - `||`. + +```js +test = false; +if(!test){ + isFalse(); // Test is false. +} + +( test || isFalse()); // Test is false. +``` +逻辑或可以用来给参数设置默认值。 + +```js +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 +``` +逻辑与可以用来避免调用undefined参数的属性时报错 +例如:- + +```js +var dog = { + bark: function(){ + console.log('Woof Woof'); + } +}; + +// 调用 dog.bark(); +dog.bark(); // Woof Woof. + +// 但是当dog未定义时,dog.bark() 将会抛出"Cannot read property 'bark' of undefined." 错误 +// 防止这种情况,我们可以使用 &&. + +dog&&dog.bark(); // This will only call dog.bark(), if dog is defined. + +``` diff --git a/_posts/zh_CN/2016-01-28-curry-vs-partial-application.md b/_posts/zh_CN/2016-01-28-curry-vs-partial-application.md new file mode 100644 index 00000000..2a63166f --- /dev/null +++ b/_posts/zh_CN/2016-01-28-curry-vs-partial-application.md @@ -0,0 +1,112 @@ +--- +layout: post + +title: 柯里化(currying)与部分应用(partial application) +tip-number: 28 +tip-username: bhaskarmelkani +tip-username-profile: https://www.twitter.com/bhaskarmelkani +tip-tldr: 柯里化(currying)与部分应用(partial application)是两种将一个函数转换为另一个有着较小普通参数个数的函数的方法。 + +categories: + - zh_CN +--- + +**柯里化(currying)** + +柯里化是使一个函数 + +f: X * Y -> R + +转变为 + +f': X -> (Y -> R) + +与用两个参数调用f不同,我们用一个参数运行f'。返回的结果是一个函数,然后用第二个参数调用此函数,得到结果。 + +如此,如果未柯里化的函数f这样调用 + +f(3,5) + +柯里化后的函数f'是这样调用的 + +f(3)(5) + +比如: +未柯里化的函数add() + +```javascript + +function add(x, y) { + return x + y; +} + +add(3, 5); // returns 8 +``` + +柯里化后的add() + +```javascript +function addC(x) { + return function (y) { + return x + y; + } +} + +addC(3)(5); // returns 8 +``` + +**柯里化的规则** + +柯里化将一个二元函数,转变为一元函数,这个函数将返回另一个一元函数。 + +curry: (X × Y → R) → (X → (Y → R)) + +Javascript Code: + +```javascript +function curry(f) { + return function(x) { + return function(y) { + return f(x, y); + } + } +} +``` + +**部分应用(partial application)** + +部分应用将一个函数 + +f: X * Y -> R + +的第一个参数固定而产生一个新的函数 + +f`: Y -> R + +f'与f不同,只需要填写第二个参数,这也是f'比f少一个参数的原因。 + +比如:将函数add的第一个参数绑定为5来产生函数plus5。 + +```javascript +function plus5(y) { + return 5 + y; +} + +plus5(3); // returns 8 +``` + +**部分应用的规则** + +部分应用使用一个二元函数和一个值产生了一个一元函数。 + +partApply : ((X × Y → R) × X) → (Y → R) + +Javascript Code: + +```javascript +function partApply(f, x) { + return function(y) { + return f(x, y); + } +} +``` diff --git a/about.md b/about.md index 2f142300..ee8de891 100644 --- a/about.md +++ b/about.md @@ -2,6 +2,7 @@ layout: page title: Introducing JavaScript Tips permalink: /about/ +lang: en --- > New year, new project. **A JS tip per day!** @@ -31,4 +32,5 @@ There are a lot of way to get update, choose your own ### Gratefulness - GIF's => [Maxi Albella](https://dribbble.com/maxialbella) -- JS Tips Theme => [Marcos Cosimi](https://github.com/markoscc) \ No newline at end of file +- JS Tips Theme => [Marcos Cosimi](https://github.com/markoscc) +- Languages flags => [Muharrem Senyil](https://dribbble.com/shots/1211759-Free-195-Flat-Flags) \ No newline at end of file diff --git a/images/flags/en.png b/images/flags/en.png new file mode 100644 index 00000000..18425bc6 Binary files /dev/null and b/images/flags/en.png differ diff --git a/images/flags/it.png b/images/flags/it.png new file mode 100644 index 00000000..101a14aa Binary files /dev/null and b/images/flags/it.png differ diff --git a/images/flags/zh_CN.png b/images/flags/zh_CN.png new file mode 100644 index 00000000..63267f70 Binary files /dev/null and b/images/flags/zh_CN.png differ diff --git a/index.html b/index.html index adf2dd06..1e147c7f 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,6 @@ --- layout: default +lang: en --- diff --git a/it/about.md b/it/about.md new file mode 100644 index 00000000..a4497c29 --- /dev/null +++ b/it/about.md @@ -0,0 +1,36 @@ +--- +layout: page +title: Introducing JavaScript Tips +permalink: it/about/ +lang: it +--- + +> New year, new project. **A JS tip per day!** + +With great excitement, I introduce these short and useful daily JavaScript tips that will allow you to improve your code writing. With less than 2 minutes each day, you will be able to read about performance, conventions, hacks, interview questions and all the items that the future of this awesome language holds for us. + +At midday, no matter if it is a weekend or a holiday, a tip will be posted and tweeted. + +### Can you help us enrich it? +Please feel free to send us a PR with your own JavaScript tip to be published here. +Any improvements or suggestions are more than welcome! +[Click to see the instructions](https://github.com/loverajoel/jstips/blob/master/CONTRIBUTING.md) + +### Let’s keep in touch + +There are a lot of way to get update, choose your own + +- [Officail Blog](http://www.jstips.co) +- [Official Twitter Account](https://twitter.com/tips_js) +- [Hubot](https://github.com/dggriffin/hubot-jstips) +- [js2016.tips](http://js2016.tips/) +- [Hingsir](http://hingsir.com/jstips-site/dist/tips/) +- [Awesomelists](https://awesomelists.top/#/repos/loverajoel/jstips) + +> Don't forget to Star the repo, as this will help to promote the project! + +### Gratefulness + +- GIF's => [Maxi Albella](https://dribbble.com/maxialbella) +- JS Tips Theme => [Marcos Cosimi](https://github.com/markoscc) +- Languages flags => [Muharrem Senyil](https://dribbble.com/shots/1211759-Free-195-Flat-Flags) \ No newline at end of file diff --git a/it/index.html b/it/index.html new file mode 100644 index 00000000..30407a71 --- /dev/null +++ b/it/index.html @@ -0,0 +1,4 @@ +--- +layout: home +lang: it +--- diff --git a/style.scss b/style.scss index c372e0ca..cff3f186 100644 --- a/style.scss +++ b/style.scss @@ -219,7 +219,6 @@ img { width: 100%; max-width: 900px; margin: 10px auto 0; - overflow: hidden; ul { margin: 0px; @@ -242,7 +241,55 @@ img { a:hover { background: #F8DA59; } + + a:hover .sub-menu ul { + display: block; + } } + + .sub-menu:hover ul { + display: block; + } + + .sub-menu { + position: relative; + + a { + padding: 12px 0 13px 2px; + font-size: 0px; + } + + a:hover { + background: none; + } + + ul { + width: 30px; + position: absolute; + z-index: 2; + display: none; + top: 39px; + left: 2px; + + li { + margin: 0px; + + a { + padding: 0px; + float: none; + font-size: 0px; + + &:hover { + background-color: none; + } + } + } + } + + img { + width: 30px; + } + } } hr { diff --git a/zh_CN/about.md b/zh_CN/about.md new file mode 100644 index 00000000..40ec6e6b --- /dev/null +++ b/zh_CN/about.md @@ -0,0 +1,35 @@ +--- +layout: page +title: Introducing JavaScript Tips +permalink: zh_CN/about/ +lang: zh_CN +--- + +> 新年, 新项目. **每天一条JS小知识!** + +怀着激动的心情, 我来介绍这些可以提高你的代码质量的短小但有用的Javascript小技巧. 每天花费不到两分钟, 你就可以了解到有关性能,习惯,技术,面试问题以及这个超棒语言提给我们的所有东西。 + +无论工作日或节假日,都将有一条小知识发布 + +### 你能帮我们丰富它吗? +请尽情将你们自己的JavaScript小知识向我们提交PR吧。我们欢迎任何意见和建议! +[点这里查看操作说明](https://github.com/loverajoel/jstips/blob/master/CONTRIBUTING.md) + +### 让我们保持联系 + +这里有很多获得更新的方式,There are a lot of way to get update, choose your own + +- [官方博客](http://www.jstips.co) +- [官方Twitter](https://twitter.com/tips_js) +- [Hubot](https://github.com/dggriffin/hubot-jstips) +- [js2016.tips](http://js2016.tips/) +- [Hingsir](http://hingsir.com/jstips-site/dist/tips/) +- [Awesomelists](https://awesomelists.top/#/repos/loverajoel/jstips) + +> 不要忘了Star我们的仓库,这将帮助我们提高此项目! + +### 鸣谢 + +- GIF's => [Maxi Albella](https://dribbble.com/maxialbella) +- JS Tips 主题 => [Marcos Cosimi](https://github.com/markoscc) +- 多语言旗帜 => [Muharrem Senyil](https://dribbble.com/shots/1211759-Free-195-Flat-Flags) \ No newline at end of file diff --git a/zh_CN/index.html b/zh_CN/index.html new file mode 100644 index 00000000..d26a6eab --- /dev/null +++ b/zh_CN/index.html @@ -0,0 +1,4 @@ +--- +layout: home +lang: zh_CN +---