Javascript Tricks - Part2

![](http://compedio.ro/fConsole/images/javascript-logo.png)

## Function.prototype.apply()
[Function.prototype.apply()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)

### 概要
指定したthisと引数(配列風のオブジェクト)で関数を呼び出す
新たなオブジェクトのためにそのメソッドを書き直すこと無く継承できる

### 配列風のオブジェクト
lengthプロパティを持つ
0以上length未満の範囲の整数を名称としたプロパティを持つ

### 呼び出し方
(Methodを保有しているObjecet).apply(Methodを実行したいObject)

```js
fun.apply(this, array)
fun.apply(this, arguments)
fun.apply(this, ['eat', 'bananas'])
fun.apply(this, new Array('eat', 'bananas'))
```
### 例

```js
// 例1 コンストラクタとして使用する
function Parent(name, age){
    this.name = name
    this.age = age
}
Parent.prototype.getInfo = function(){
    console.log(this.name + ", " + this.age + "years old")
}
function Child() {
  Parent.apply(this, arguments);
  this.sports = arguments[2] 
}

Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child

var parent = new Parent("father", 29)
var child = new Child("son", 3, "soccer")
child.getInfo()
// son, 3years old

// 例2 なりすましに使用する
var soccer = {
	title:  'Soccer',
	getInfo: function(number, rule){
		console.log( this.title +  ' needs ' + number + " players")
		console.log( this.title +  " has " + rule)
	}
}
 
var baseball = { title: 'Baseball' }

soccer.getInfo(11, "Time Limit" ) 
// Soccer needs 11 players
// Soccer has Time Limit
soccer.getInfo.apply( baseball,  [9, "No Time Limit"] )
// Baseball needs 9 players
// Baseball has No Time Limit

// 例3 Math.max,minと利用する
// 配列とループを駆使すること無く処理が可能
var numbers = [5, 6, 2, 3, 7];
var max = Math.max.apply(null, numbers); 
// 7
var min = Math.min.apply(null, numbers);
// 2
```

## Function.prototype.bind()
[Function.prototype.bind()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)

### 概要
新たな関数を生成

### 例

```js
// 例1 束縛された関数を生成する
var age = 9
var module = {
  age: 81,
  methodAge: function() { return this.age; }
}
module.methodAge()
// thisはmoduleオブジェクト
// 81
var globalAge = module.methodAge
globalAge();
// thisはglobalオブジェクト
// 9
var newAge = globalAge.bind(module);
newAge();
// thisをmoduleに強制した関数作成
// 81

// 例2 部分的に適用された関数
//引数が指定された関数を生成
//指定された引数を先頭にして束縛された関数に渡される
function list() {
  return Array.prototype.slice.call(arguments)
}
var list1 = list(1, 2, 3)
// [1, 2, 3]
var listPattern37 = list.bind(null, 37)
var list2 = listPattern37()
// [37]
var list3 = listPattern37(1, 2, 3)
// [37, 1, 2, 3]

// 例3 setTimeoutと使う
function MakeFriends() {
  this.friendCount = Math.ceil( Math.random() * 100 )
}

MakeFriends.prototype.made = function() {
  window.setTimeout( this.declare.bind(this), 2000 );
};

MakeFriends.prototype.declare = function() {
    console.log('Now I have ' + this.friendCount + ' friends!');
    this.friendCount++
};

var Ken = new MakeFriends
Ken.made()

// 例4 ショートカットを作成する
var lg = console.log.bind(console)
function A(){
    lg("Short Cut A!")
}
function B(){
    lg("Short Cut B!")
}
```

## 分割代入
[分割代入](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)

```js
[a, b, ...rest] = [1, 2, 3, 4, 5]
console.log(a) 
// 1
console.log(b) 
// 2
console.log(rest) 
// [3, 4, 5]
```

## `function*`ジェネレーター
[function*](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/function*)

ジェネレーターは処理を抜け出すことも後から復帰することもできる関数
変数の値は復帰しても保存される
1. ジェネレーター関数呼び出し 
2. iteratorオブジェクトが返される　
3. next()メソッドが呼ばれる　
4. 最初のyieldかyield*に達するまで実行
5. valueプロパティdoneプロパティを持つオブジェクトを返す

```js
function* idMaker(){
    var index = 0
    while(index < 3){
        yield index++
    }
}
var gen = idMaker()
console.log(gen.next().value)
// 0
console.log(gen.next().value)
// 1
console.log(gen.next().value)
// 2
console.log(gen.next().value)
// undefined

function* anotherGenerator(i){
    yield i + 1
    yield i + 2
}
function* generator(i){
    yield i
    yield* anotherGenerator(i) 
    yield i + 10
}
var gen = generator(10)
console.log(gen.next().value)
// 10
console.log(gen.next().value)
// 11
console.log(gen.next().value)
// 12
console.log(gen.next().value)
// 20
console.log(gen.next().value)
// undefined
```

## Rest Parameters
[Rest Parameters](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope/rest_parameters)

```js
// ArrayなのでArrayメソッドが使える
function sortArgs(...Args){
    var sor = Args.sort()
    return sor
}
console.log(sortArgs(5,3,7,1))
// [ 1, 3, 5, 7 ]
function sortArguments(...Args){
    var sor = arguments.sort()
    return sor
}
// console.log(sortArguments(5,3,7,1))
// Arrayではないためerror

function multiply(mul, ...Args){
    return Args.map(function(elem){
        return mul * elem
    })
}
var arr = multiply(2, 1, 2, 3)
console.log(arr)
// [ 2, 4, 6 ]
```