From 4abda013cf3d762e24c4902cbaf3ab9a8a05cb87 Mon Sep 17 00:00:00 2001 From: sjfkai Date: Sun, 14 Feb 2016 18:03:25 +0800 Subject: [PATCH] translate tip42, 43 and 44 into zh_CN --- .../2016-02-11-preventing-unapply-attacks.md | 56 +++++++++++++++++ ...se-destructuring-in-function-parameters.md | 29 +++++++++ .../2016-02-13-know-the-passing-mechanism.md | 63 +++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 _posts/zh_CN/2016-02-11-preventing-unapply-attacks.md create mode 100644 _posts/zh_CN/2016-02-12-use-destructuring-in-function-parameters.md create mode 100644 _posts/zh_CN/2016-02-13-know-the-passing-mechanism.md diff --git a/_posts/zh_CN/2016-02-11-preventing-unapply-attacks.md b/_posts/zh_CN/2016-02-11-preventing-unapply-attacks.md new file mode 100644 index 00000000..fa008430 --- /dev/null +++ b/_posts/zh_CN/2016-02-11-preventing-unapply-attacks.md @@ -0,0 +1,56 @@ +--- +layout: post + +title: 预防unapply攻击 +tip-number: 42 +tip-username: emars +tip-username-profile: https://twitter.com/marseltov +tip-tldr: 冻结内置对象的原型方法。 + +categories: + - zh_CN +--- + +重写内置对象的原型方法,攻击者可以重写代码达到暴漏和修改已绑定参数的函数。这在es5的方法实现`polyfill`时是一个严重的安全漏洞。 + +```js +// bind polyfill 示例 +function bind(fn) { + var prev = Array.prototype.slice.call(arguments, 1); + return function bound() { + var curr = Array.prototype.slice.call(arguments, 0); + var args = Array.prototype.concat.apply(prev, curr); + return fn.apply(null, args); + }; +} + + +// unapply攻击 +function unapplyAttack() { + var concat = Array.prototype.concat; + Array.prototype.concat = function replaceAll() { + Array.prototype.concat = concat; // restore the correct version + var curr = Array.prototype.slice.call(arguments, 0); + var result = concat.apply([], curr); + return result; + }; +} +``` + +上面的函数声明忽略了函数bind的`prev`参数,意味着调用`unapplyAttack`之后首次调用`.concat`将会抛出错误。 + +使用[Object.freeze](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze),可以使对象不可变,你可以防止任何内置对象原型方法被重写。 + + +```js +(function freezePrototypes() { + if (typeof Object.freeze !== 'function') { + throw new Error('Missing Object.freeze'); + } + Object.freeze(Object.prototype); + Object.freeze(Array.prototype); + Object.freeze(Function.prototype); +}()); +``` + +你可以[在这里](https://glebbahmutov.com/blog/unapply-attack/)阅读更多关于unapply攻击。 \ No newline at end of file diff --git a/_posts/zh_CN/2016-02-12-use-destructuring-in-function-parameters.md b/_posts/zh_CN/2016-02-12-use-destructuring-in-function-parameters.md new file mode 100644 index 00000000..f4e9defa --- /dev/null +++ b/_posts/zh_CN/2016-02-12-use-destructuring-in-function-parameters.md @@ -0,0 +1,29 @@ +--- +layout: post + +title: 函数参数内使用解构 +tip-number: 43 +tip-username: dislick +tip-username-profile: https://github.com/dislick +tip-tldr: 你知道在函数参数内也可以使用解构吗? + +categories: + - zh_CN +--- + +大家一定对[ES6解构赋值](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)非常熟悉。但是你知道在函数参数里也可以使用它吗? + +```javascript +var sayHello = function({ name, surname }) { + console.log(`Hello ${name} ${surname}! How are you?`); +}; + +sayHello({ + name: 'John', + surname: 'Smith' +}); +``` + +这对于接收可选参数的函数,是很棒的。 + +> 请注意解构赋值在Node.js和大部分浏览器中仍然不可用。但是想自己尝试的话可以在Node.js下使用`--harmony-destructuring`标记。 \ No newline at end of file diff --git a/_posts/zh_CN/2016-02-13-know-the-passing-mechanism.md b/_posts/zh_CN/2016-02-13-know-the-passing-mechanism.md new file mode 100644 index 00000000..002abae5 --- /dev/null +++ b/_posts/zh_CN/2016-02-13-know-the-passing-mechanism.md @@ -0,0 +1,63 @@ +--- +layout: post + +title: 了解传值机制 +tip-number: 44 +tip-username: bmkmanoj +tip-username-profile: https://github.com/bmkmanoj +tip-tldr: JavaScript理论上说只传递原始类型和对象(或引用)类型的值。在引用类型的情况下引用值本身通过值传递。 + +categories: + - zh_CN +--- + +理论上,JavaScript通过值传递。它既不是值传递也不是引用传递,具体取决于它的真实场景。要理解传值机制,看一下下面两个实例代码和解释。 + +### 实例 1 + +```js + +var me = { // 1 + 'partOf' : 'A Team' +}; + +function myTeam(me) { // 2 + + me = { // 3 + 'belongsTo' : 'A Group' + }; +} + +myTeam(me); +console.log(me); // 4 : {'partOf' : 'A Team'} + +``` + +在上面的实例里`myTeam`被调用的时候,JavaScript *传递*`me`*对象的引用值,因为它是一个对象*。而且调用本身建立了同一个对象的两个独立的引用,(虽然在这里的的命名都是相同的,比如`me`, 这有些无调行,而且给我们一个这是单个引用的印象)因此,引用变量本身是独立的。 + +当我们在#`3`定义了一个新的对象,我们完全改变了`myTeam`函数内的引用值,这对此函数作用域外的原始对象是没有任何影响的,外作用域的引用仍保留在原始对象上,因此从#`4`输出去了。 + + +### 实例 2 + +```js + +var me = { // 1 + 'partOf' : 'A Team' +}; + +function myGroup(me) { // 2 + me.partOf = 'A Group'; // 3 +} + +myGroup(me); +console.log(me); // 4 : {'partOf' : 'A Group'} + +``` + +当`myGroup`调用时,我们将对象`me`传给函数。但是与实例1的情况不同,我们没有指派`me`变量到任何新对象,有效的说明了`myGroup`函数作用域内的对象引用值依旧是原始对象的引用值,而且我们在作用域内修改对象的参数值同样有效的修改了原始对象的参数。因此你得到了#`7`的输出结果。 + +所以后面的例子是否说明javascript是引用传递呢?不,并没有。请记住,*如果是对象的话,JavaScript将引用按值传递*。这种混乱往往发生在我们没有完全理解什么通过引用传递的情况下。这就是确切的原因,有些人更愿意称它为*call-by-sharing*。 + + +*此文最初被作者发表在[js-by-examples](https://github.com/bmkmanoj/js-by-examples/blob/master/examples/js_pass_by_value_or_reference.md)* \ No newline at end of file