for...of を使って基本的な文字列メソッドを定義する

2015年1月にリリースされた io.js では `for...of` を使うことができる。`for...of` はサロゲートペアを考慮する。`String.prototype.codePointAt()` よりもコードがコンパクトになる。`codePointAt` のコードの例はこちらの[記事](http://qiita.com/masakielastic/items/6c566730f7d7e924ad35)を参照。

## 文字数を求める

```js
if (!String.prototype.countChar32) {
    String.prototype.countChar32 = function() {
        var count = 0;

        for (var c of this) {
            ++count;
        }

        return count;
    };
}

var str = '\uD842\uDFB7野家';
console.log(3 === str.countChar32());
```

## 指定したインデックスに対応する1文字取り出す

```js
if (!String.prototype.char32At) {
    String.prototype.char32At = function(offset) {

        var index = 0;

        for (var c of this) {

            if (offset === index) {
                return c;
            }

            ++index;
        }

        return '';
    };
}

var str = '\uD842\uDFB7野家';
console.log('\uD842\uDFB7' === str.char32At(0));
```

## 文字列を逆順に並べ替える

```js
if (!String.prototype.reverse) {
    String.prototype.reverse = function() {

        var ret = '';

        for (var c of this) {
            ret = c + ret;
        }

        return ret;
    };
}

var str = '\uD842\uDFB7野家';
console.log('家野\uD842\uDFB7' === str.reverse());
```

## 部分文字列を取り出す

```js
if (!String.prototype.substr32) {
    String.prototype.substr32 = function(pos, length) {

        var ret = '';
        var last = pos + length - 1;
        var index = 0;

        for (var c of this) {

            if (index >= pos && last >= index) {
                ret += c;
            }

            if (index === last) {
                return ret;
            }

            ++index;
        }

        return ret;
    };
}

var str = '\uD842\uDFB7野家';
console.log('野' === str.substr32(1, 1));
```

## 部分文字列を取り出す・その2

関数型言語に見られる `take` と `drop` を定義する。

```js
if (!String.prototype.take) {
    String.prototype.take = function(length) {

        var ret = '';
        var index = 0;

        for (var c of this) {

            if (index === length) {
                return ret;
            }

            ret += c;
            ++index;
        }

        return ret;
    };
}

var str = '\uD842\uDFB7野家';
console.log('\uD842\uDFB7' === str.take(1));
```

```js
if (!String.prototype.drop) {
    String.prototype.drop = function(length) {

        var ret = '';
        var index = 0;

        for (var c of this) {
            ++index;

            if (index <= length) {
                continue;
            }

            ret += c;
        }

        return ret;
    };
}

var str = '\uD842\uDFB7野家';
console.log('野家' === str.drop(1));
```


## 1文字ごとにコールバックを適用する


```js
if (!String.prototype.eachChar) {
    String.prototype.eachChar = function(callback) {

        for (var c of this) {
            callback(c);
        }

    };
}

var str = '\uD842\uDFB7野家';
str.eachChar(function(c) {
    console.log(c);
});
```

## コードポイントごとにコールバックを適用する

```js
if (!String.prototype.eachCodePoint) {
    String.prototype.eachCodePoint = function(callback) {

        for (var c of this) {
            callback(c.codePointAt(0));
        }

    };
}

var str = '\uD842\uDFB7野家';
str.eachCodePoint(function(cp) {
    console.log('U+' + cp.toString(16).toUpperCase());
});
```