カテゴリー別アーカイブ: ES6

well-known Symbolとは| 海外記事「Detailed overview of well-known symbols」の和訳

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-15-10-19-28
参照記事

SymbolはECMAScript2015の新しいプリミティブ型です。それはユニークな識別子を作ることができます

let uniqueKey = Symbol('SymbolName')

Symbolはオブジェクトの中のプロパティのkeyとして使うことが可能です。

(上のように使ったら)JavaScriptは「well-konwn symbols」として公開されたsymbolのリストを扱えます。

「Well-known symbols」はビルドインJavaScriptのアルゴリズムとして使われています。
例えば
Symbol.iterator はarrayやstringの要素を イテレートすること、もしくはあなた自身が定義したイテレーター関数などに利用されています。

それらの特別なSymbol等(ら)は重要です

なぜならそれらはオブクトのシステムプロパティで独自の振る舞いを定義できるからです。

それらをJSの中で使えるのです。

「唯一」として存在し、文字列イテレーターの代わりにkeyとしてシンボルを使うことは
新しいオブジェクトに新しい機能を追加することを簡単に可能にします

この記事ではwell-known Symbolのリストを通して、それらのコード中での快適な使い方を説明します

多くの場合単純化のために well-known Symbol.<name> は @@<name>形式に省略されています。

例えば

Symbol.iterator は @@iterator

Symbol.toPrimitiveは @@toPrimitive

「オブジェクトは @@iteratorメソッドを持つこと」を可能にすると言うことができます。

そのことは、オブジェクトはSymbol.iteratorと名付けられた、関数を所有するプロパティを持っていることを示しています。

{ [Symbol.iterator]: function(){...} }.

目次

  1. Symbolを短く紹介
  2. オブジェクトイテレータブルを作る@@iterator
  3. instanceofをカスタマイズする@@hasInstance
  4. オブジェクトをプリミティブに変換する@@toPrimitive
  5. オブジェクトのデフォルト記述を作成する@@toStringTag
  6. 派生されたオブジェクトを作成する@@species
  7. オブジェクトのような正規表現を作成 @@match, @@replace, @@search, @@split
  8. 配列要素に対してのオブジェクトをフラットにする@@isConcatSpreadable
  9. withの中のアクセス可能にするプロパティに対しての@@unscopables
  10. 終わりに

1.Symbolを短く紹介

Symbolは数値型、真偽値、文字列型のような唯一かつ不変なプリミティブ型です
symbolを作成するために、名前を引数とするオプションでSymbol関数を実行します。

  let mySymbol = Symbol();
  let namedSymbol = Symbol('myName');
  typeof mySymbol;
  //'symbol'
  typeof namedSymbol
  //'symbol'
  

mySymbolとnamedSymbolは symbolプリミティブです。 namedSymbolは ‘myName’ネームとの結びつきを持っていて、
それはデバッキングに対してよく使われます。

いつでもSymbol()が実行されることは重要で、
新しく且つユニークなsymbolが作られます。
2つのsymbolはたとえそれらが同じ名前を持っていてもユニークです。

  let first = Symbol();
  let second = Symbol();
  first === second;
  //false
  let firstNamed = Symbol('Lorem');
  let secondNamed = Symbol('Lorem');
  firstNamed === secondNamed; 
  //false
  

ユニークなシンボルで作られた first と second は違うものです。
firstNamed と secondNamed は ‘Lorem’ という同じ名前を持ちますが、違うものです

Symbols は オブジェクトのプロパティに対してkeyになることができます。
オブジェクトリテラル それか クラス定義の中で、
コンピューティッドプロパティネーム構文の [symbol]は使用は不可欠です。

  let stringSymbol = Symbol('String');
  let myObject = {
   number: 1,
   [stringSymbol]: 'Hello World'
 };
  myObject[stringSymbol];//'Hello World'
  Object.getOwnPropertyNames(myObject); //['number']
  Object.getOwnPropertySymbols(myObject);//['Symbol(String)']
  
  

リテラルからmyObjectを定義している際、コンピューティッド構文はsymbol[stringSymbol]からのプロパティkeyを設定するために使われます。

シンボルで定義されたプロパティはObject.keys()やObject.getOwnPropertyNames()関数を使ってアクセスできません。

それらにアクセスするためには特別な関数であるObject.getOwnPropertySymbols()を呼びます。

keyとしてシンボルを使うことは重要な観点です。
特別なSymbol(well-known symbols)はイテレーションやプリミティブなオブジェクト、文字変換等のようなカスタムオブジェクトを定義することを可能にします。

well-known symbolsは列挙不可、書き換え不可、再設定不可 を可能にした Symbol関数オブジェクトのプロパティです
単純、Symbol.iteratorやSymbol.hasInstance等、それらを得るためのSymbol関数オブジェクト上のプロパティアクセサーを使います

このようなwell-known symbolsのリストを得ることができます。

Object.getOwnPropertyNames(Symbol);
//["hasInstance", "isConcatSpreadable", "iterator", "toPrimitive", "toStringTag", "unscopables","match", "replace", "search", "split", "species", ...];
typeof Symbol.iterator; 
//'symbol'

Object.getOwnPropertiesNames(Symbol) は Symbol関数オブジェクトの所有されたプロパティを返し、
well-known symbolsのリストを含んでいます。
Symbol.iteratorの進む「型」は’symbol’です。

オブジェクトイテレータブルを作る@@iterator

Symbol.iteratorは多分より知られているsymbolです。
それはオブジェクトがfor…of文やスピリードオペレータによってどのように使われ、イテレートされるべきかを定義することを可能にします

多くのstrings、arrays、maps、sets、などのビルドイン型はイテレータブルで、@@iteratorメソッドを持ちます。

let myString = 'Hola'
typeof myString[Symbol.iterator];// 'function'
for(let char of myString) {
 console.log(char); //logs on each iterator 'H', 'o', 'I', 'a'
}
[...myString];// ['H', 'o', 'I', 'a']

文字列のプリミティブ型のmyString はSymbol.iteratorプロパティを持ちます。
プロパティは文字列のキャラクターをイテレートすることに使うメソッドを所有します。

Symbol.iteratore という名前のメソッドを定義するオブジェクトはイテラブルプロトコルに準拠しています。
メソッドは イテレータープロトコルに準拠したオブジェクトを返す必要があります。

イテレータプロトコルオブジェクトは{value: , done: }を返すnext()メソッドを持つ必要があります。

カスタムイテレータの定義の仕方を理解しましょう。
下の例はmyMethods というイテラブルオブジェクトを作成、myMethodsはメソッドの所有を可能にします。

  function methodsIterator(){
   let index = 0;
   let methods = Object.keys(this).filter((key) = &gt; {
     return typeof this[key] === 'function';
   }).map(key =&gt; this[key]);
   return {
     next: ()=&gt; ({//Conform to Iteretor protocol
      done: index &gt;= methods.length,
      value: methods[index++]
     })
   };
  }
  let myMethods = {
    toString: function(){
     return '[object myMethods]';
    },
    sumNumbers: function(a, b) {
     return a + b;
    },
    numbers: [1,5,6],
    [Symbol.iterator]: methodsIterator //Comform to Iteratable Protocol
  };
  for ( let method of myMethods) {
     console.log(method); //logs methods `toString` and `sumNumbers`
   }

methodsIterator() は イテレーターオブジェクト{next : function(){…}}を返す関数です。
myMethodsの中でオブジェクトプロパティはkeyとしてSymbol.iterator、値としてmethodsIteratorがセットアップされます

これはmyMethods をイテラブルにさせ、
for…ofループの中のsumNumbers()とtoString()らのオブジェクトが所有するメソッドを渡すことができます

それに加えて、[…myMethods]かArray.from(myMethods)を呼ぶことによってそれ等のメソッドを得ることができます。

@@iterator プロパティ は ジェネレーター関数も受け取り、そのジェネレーター関数を値にさせることもできます

@@iteratorメソッドでFibonacci シーケンスを生成する class Fibonacci を作ってみましょう

  class Fibonacci {  
  constructor(n) {
    this.n = n;    
  }
  *[Symbol.iterator]() {
    let a = 0, b = 1, index = 0;
    while (index &lt; this.n) { index++; let current = a; a = b; b = current + a; yield current; } } } let sequence = new Fibonacci(6); let numbers = [...sequence]; numbers; // =&gt; [0, 1, 1, 2, 3, 5]
  

*[Symbol.iterator](){…} はジェネレーター関数はクラスメソッドということを明らかにします。
Fibonacciクラスのインスタンスはイテラブルプロトコルに準拠します。

そしてシーケンスインスタンスは[…sequence]スプレッドオペレーターで使われます。
スプレッドオペレーターは生成された数値からの配列を作成するために@@iterator メソッドを呼びます。

なので 結果は最初のFibonacci 数値の5の配列です。

もしプリミティブ型かオブジェクトが@@iteratorメソッドを持つなら、それらは下のコンストラクタ内で適応することができます。

・for…ofループの中での要素を超えイテレートする
・スプレッドオペレータ[…iterableObject]を使って要素の配列を作成する
・Array.from(iterableObject)を使って要素の配列を作成する
・他のジェネレーターへの代理する為のyield*式の中で
・Map(iterableObject)、WeakMap(iterableObject)、Set(iterableObject)、WeakSet(iterableObject)に対してのコンストラクタの中で
・静的メソッドPromise.all(iterableObject)、Promise.race(iterableObject)であるPromiseの中で

instanceofをカスタマイズする@@hasInstance

デフォルトでは obj instanceof Constructor オペレーターはConstructor.prototypeオブジェクトを含むObjectのprototypeのチェーンかどうか検証する
例題をみていきましょう

function Constructor(){
//constructor code
}
let obj = new Constructor();
let objProto = Object.getPrototypeOf(obj);
objProto === Constructor.prototype // true
obj instanceof Construcotr;//true
obj instanceof Object;//true

obj instanceof Constructor はtrueかを評価します。なぜならobjのprototypeはConstructor.prototypeと同等だからです。
instanceof 検証はobjのprototypeチェーンも検証し、したがって、
obj instanceof Object は trueです。

多くのアプリケーションはprototypeに対処し、instanceの検証を必要としません

幸い、カスタマイズのinstanceof 評価を呼ぶことができる@@hasInstancseを定義できます。
obj instance Type はType[Symbol.hasInstance](obj)と同等です。

例えば、もしobjectかプリミティブがイテラブルの場合の検証をしましょう。

class Iterable {  
  static [Symbol.hasInstance](obj) {
    return typeof obj[Symbol.iterator] === 'function';
  }
}
let array = [1, 5, 5];  
let string = 'Welcome';  
let number = 15;  
array instanceof Iterable;  // =&gt; true  
string instanceof Iterable; // =&gt; true  
number instanceof Iterable; // =&gt; false 
  

イテラブルは@@hasInstance静的メソッドを含むクラスです。
このメソッドは供給されたobjパラメータがイテラブルか検証します
後のイテラブルかは違うタイプの値か検証に使われます
配列と文字列は はイテラブルで数値はそうではありません

個人的に単にinstanceof と constructorで@@hasInstanceを使うことは
isIterable(array)を呼ぶより
嬉しいです。

array instanceof Iterable は配列がイテラブルプロトコルに準拠しているかの検証されることとしてオススメします。

オブジェクトをプリミティブに変換する@@toPrimitive

プロパティの値記述としてのSymbol.toPrimitive 使用はオブジェクトからプリミティブへの変換する関数です。
@@toPrimitive メソッドは1つのnumberかstringかデフォルトを取るパラメーター[ヒント]を持ちます。
ヒントパラメーターは返すべきプリミティブの型の提案を示します

例えば 配列インスタンスを@@toPrimitiveメソッドで改善しましょう。

  function arrayToPrimitive(hint) {  
  if (hint === 'number') {
    return this.reduce((sum, num) =&gt; sum + num);
  } else if (hint === 'string') {
    return `[${this.join(', ')}]`;
  } else {
    // hint is default
    return this.toString();    
  }
}
let array = [1, 5, 3];  
array[Symbol.toPrimitive] = arrayToPrimitive;  
// array to number. hint is 'number'
+ array; // =&gt; 9
// array to string. hint is 'string'
`array is ${array}`; // =&gt; 'array is [1, 5, 3]'
// array to default. hint is 'default'
'array elements: ' + array; // =&gt; 'array elements: 1,5,3'  
  

arrayToPrimitive(hint) は配列をhintから独立しているプリミティブへ変換する関数です

その割り当てである array[Symbol.toPrimitive] = arrayToPrimitive は新しい変換メソッドを使えるように配列を作ります。

+array は@@toPrimitiveメソッドを’number’で呼びます。

配列は数値に変換され、9の要素配列の合計です。
プリミティブ変換は'[1, 5, 3]’
最後の ‘array elements: ‘ + arry は変換用のhintデフォルトを使います。
この場合 arrayは’1,5,3’に評価されます。

@@toPrimitive メソッドは オブジェクトがプリミティブ型と相互作用するとき使われます。
・object == primitive 同等操作の中で
・追加、連結操作 object + primitive
・減算操作の中で object – primitive
・オブジェクトがプリミティブへ強制されたときの違う状況で String(object), Number(objet)

オブジェクトのデフォルト記述を作成する@@toStringTag

 

プロパティを示すためにSymbol.toStringTagを使います。プロパティの値はオブジェクト型が記述された文字列です。

@@toStringTag メソッドは Object.prototype.toString()として使われています。

Object.prototype.toString()の仕様書は多くのJavaScript型はデフォルトとしてタグを持っていることを示します。

let toString = Object.prototype.toString;  
toString.call(undefined); // =&gt; '[object Undefined]'  
toString.call(null);      // =&gt; '[object Null]'  
toString.call([1, 4]);    // =&gt; '[object Array]'  
toString.call('Hello');   // =&gt; '[object String]'  
toString.call(15);        // =&gt; '[object Number]'  
toString.call(true);      // =&gt; '[object Boolean]'  
// etc for Function, Arguments, Error, Date, RegExp
toString.call({});        // =&gt; '[object Object]'  

これらの型はプロパティSymbol.toStringTagを持っていません。
しかしObject.prototype.toString()アルゴリズムはそれらとは分けて評価します。

多くの他のJavaScript型はSymbol、ジェネレーター関数、maps、promises、など、で@@toStringTagプロパティを定義します。
ちょっと見てみましょう。

let toString = Object.prototype.toString;  
let noop = function() {};

Symbol.iterator[Symbol.toStringTag];   // =&gt; 'Symbol'  
(function* () {})[Symbol.toStringTag]; // =&gt; 'GeneratorFunction'
new Map()[Symbol.toStringTag];         // =&gt; 'Map'  
new Promise(noop)[Symbol.toStringTag]; // =&gt; 'Promise'

toString.call(Symbol.iterator);   // =&gt; '[object Symbol]'  
toString.call(function* () {});   // =&gt; '[object GeneratorFunction]'  
toString.call(new Map());         // =&gt; '[object Map]'  
toString.call(new Promise(noop)); // =&gt; '[object Promise]'  

上のサンプルでみるように、
多くのJavaScript型はそれらが所有する@@toStringTagプロパティを定義します。

オブジェクトが型や@@toStringTagプロパティが提供されていない他のケースでは
単に’Object’としてタグされます。
もちろん@@toStringTagプロパティでカスタム定義できます。

let toString = Object.prototype.toString;

class SimpleClass {}  
toString.call(new SimpleClass); // =&gt; '[object Object]'

class MyTypeClass {  
  constructor() {
    this[Symbol.toStringTag] = 'MyType';
  }
}
toString.call(new MyTypeClass); // =&gt; '[object MyType]'
"[object MyType]"

new SimpleClass インスタンスは @@toStringTagが定義されていなかった。
Object.prototype.toString()はそれに対してデフォルトの'[object Object]’を返します。
MyTypeClassコンストラクタの中で、インスタンスはカスタムタグ’MyType’で設定されました。

そのようなObject.prototype.toString()クラスインスタンスに対してカスタム型記述は'[object MyType]’を返します。

@@toStringTagは下位互換の点で存在していることに注意してください。

その習慣はなやましいです。
あなたは他のオブジェクト型の線引きするための違う方法(instanceofかtypeof のような)を使うべきと思うだろう

派生オブジェクトを作成する@@species

Symbol.speciesプロパティの値は派生オブジェクト を作成するために使われたコンストラクタ関数です。
多くのJavaScriptコンストラクタはコンストラクタ自身と同等の@@speciesの値を持っています。

Array[Symbol.species] === Array;   // => true  
Map[Symbol.species] === Map;       // => true  
RegExp[Symbol.species] === RegExp; // => true  

最初に注意したいのは派生オブジェクトは元のオブジェクト上の操作後に作成されるものです。
例えばオリジナルな配列上の.map()メソッドを呼ぶと、派生オブジェクトを返します(配列結果をマッピングした)

大抵、派生オブジェクトはオリジナルのオブジェクトとして同じコンストラクタを持ち、もっていることを期待されます。
しかし時々カスタムコンストラクタを示すことが必要になります。

@@speciesプロパティはその助けとなります。

Arrayコンストラクタを子classのMyArrayとして使いやすいメソッドを加えるために拡張する際のシナリオを想定してください。

後でMyArray classインスタンスがmap()で使われるとき、
Arrayのインスタンスである必要があり、MyArrayはその子供ではない場合、それをします。

@@speciesプロパティアクセサを定義し派生したArrayコンストラクタオブジェクトを示します。

class MyArray extends Array {  
  isEmpty() {//拡張
    return this.length === 0;
  }
  static get [Symbol.species]() {//プロパティアクセサを定義する
    return Array;//派生オブジェクトを示す
  }
}
let array = new MyArray(3, 5, 4);  
array.isEmpty(); // => false  
let odds = array.filter(item => item % 2 === 1);  
odds instanceof Array;   // => true  
odds instanceof MyArray; // => false  //違うことを示す

静的アクセさプロパティのMyArrayでstatic get [Symbol.species](){}が定義されています。
それは派生オブジェクトはArrayコンストラクタを持つべきだという指示です。
array.filter()メソッドはArrayを返し、配列要素を選別した後に

@@species アクセサプロパティは.map()、.concat()、.slice()、.splice()のようなArrayとTypeArrayメソッドで使われ、派生オブジェクトを返します。
それはmaps、正規表現オブジェクト、プロミスなどの拡張しているものに対して有効で、オリジナルコンストラクタをキープできるのです。

オブジェクトのような正規表現を作成 @@match, @@replace, @@search, @@split

JavaScriptのString プロトタイプは 正規表現オブジェクトを受け入れる4つのメソッドを持っています。

・String.prototype.match(regExp)
・String.prototype.replace(regExp, newSubstr)
・String.prototype.search(regExp)
・String.prototype.split(regExp, limit)

ECMAScript 2015は それらの4つのメソッドは正規表現以外のタイプをプロパティの値とされた結果の関数を「条件」を定義することで、受け入れることができます。

@@match, @@replace, @@search and @@split.

面白いことにそれらのメソッドが定義された正規表現prototypeはsymbolを使うことで定義できます

typeof RegExp.prototype[Symbol.match];   // => 'function'  
typeof RegExp.prototype[Symbol.replace]; // => 'function'  
typeof RegExp.prototype[Symbol.search];  // => 'function'  
typeof RegExp.prototype[Symbol.split];   // => 'function'  

カスタムパターンclassを作成してみましょう。
下の例はRegExpの代わりに使うことができる単純なclass定義です。

class Expression {  
  constructor(pattern) {
    this.pattern = pattern;
  }
  [Symbol.match](str) {
    return str.includes(this.pattern);
  }
  [Symbol.replace](str, replace) {
    return str.split(this.pattern).join(replace);
  }
  [Symbol.search](str) {
      return str.indexOf(this.pattern);
  }
  [Symbol.split](str) {
      return str.split(this.pattern);
  }
}
let sunExp = new Expression('sun');  
'sunny day'.match(sunExp);            // => true  
'rainy day'.match(sunExp);            // => false  
'sunny day'.replace(sunExp, 'rainy'); // => 'rainy day'  
"It's sunny".search(sunExp);          // => 5
"daysunnight".split(sunExp);          // => ['day', 'night']

Expression classは@@match, @@replace, @@search and @@split. を定義しています。
後のsunExp インスタンスは 返すstring メソッドで使われて、だいたい擬似的な正規表現です。

配列要素に対してのオブジェクトをフラットにする@@isConcatSpreadable

————————————————-
以降はただいま翻訳中。。
長いな。。あと3つか。。

withの中のアクセス可能にするプロパティに対しての@@unscopables

終わりに

【JavaScript/ES6】ECMAScript2015にひっそりある「new.target」。stackoverflowにあるnew.targetって何?を読む

まずこれを読む
仕様

・new.targetは関数かコンストラクタかがnewを利用して呼ばれたかどうかを検出できる
・new.targetはコンストラクタか関数かの参照が返る。普通の関数だったらundefinedが返る

つづいてこれを読む
http://stackoverflow.com/questions/32450516/what-is-new-target

new.targetを使うと。。

私の英語の和訳

newなしで呼ばれたかどうかの検出することができる

【JavaScript/ES6】ECMAScript2015の「new.target」って何?を読む

newで呼ばれたかnew.targetを判定している


ただそれ自体本当の目的でではなく

どのようにclass継承したかだけではなく、どのようなビルドインオブジェクトから継承されているかをしれる

new Xとしてclassコンストラクタを呼んだ時
thisはまだ初期化されていない

【JavaScript/ES6】ECMAScript2015の「new.target」って何?を読む

superより先にthisを参照した結果Error

コンストラクタのbodyに入った時オブジェクトはまだ作られていない
thisはsuper()で、superコンストラクタを呼んで作られて得られる。

インスタンスは呼ばれたコンストラクタの元のprototypeオブジェクトを継承する
その時、newTargetの出番。
newTargetはsuperで実行した一番外側で呼ばれたnewのコンストラクタを掴む。

【JavaScript/ES6】ECMAScript2015の「new.target」って何?を読む

【JavaScript/ES6】ECMAScript2015の「new.target」って何?を読む

new.target.nameをつけてみる
スクリーンショット 2016-08-21 10.21.00

superで呼んだ呼び出し先コンストラクタ内で呼び出し元のコンストラクタの名前がわかる

呼んだ呼んだ言いすぎてごめんねー

※that’s where newTarget comes into the play.(newTargetの出番です)

あ、ありがとーー
ではまたーーーー

【JavaScript】去り際が格好いいECMAScript2015「WeakMap」のイケメンさがわかる記事

Resources
「What Are Weakmaps In ES6?」
ES6 Everyday: WeakMaps

One of the biggest caveats (by design) is the lack of size, followed by the inability to use strings as key names and also the inability to iterate over a WeakMap.

・なぜweakか。ガーベージコレクションの対象なので。
・ユースケースはDOMelementでdataとして扱う時。DOMに対してデータを格納でき、DOMが削除、存在していないならweakMapの内部の参照はガーベージコレクションの対象になる。明示的な要請なしにclean upしてくれる。(Jqueryのようにいつまでも参照を残さないことを意味する)
・keynameとしてstring型が使えない
・keyはnullじゃないObject、keyはany
・iteratableではない

///////////////
This allows us to treat DOM objects as the objects they are complete with their own states and data independent of everything else within your application that will be garbage collected if they are removed.
///////////////

JS Bin on jsbin.com

【JavaScript】Object.crateとassignを使ってnewしないでインスタンスを作る「FactoryFunction」

大変興味深い記事見つけました

ざっくり何をいっているかというと
「あなたがprototypeを理解していないならJavaScriptを理解していない」
衝撃的。。
classの継承はprototypeの継承と同じことですか??スタイルの違いですか??
No
classは青写真、設計図、subクラスとの関係。
いいかえるならclassがないとインスタンスは作れない
インスタンスメソッドはそれ自体class定義されていないと実行できない
まずインスタンスを作ってインスタンス上でメソッドを実行しなくてはならない。

prototype継承は
他のインスタンスから継承しているインスタンス。
prototype委譲して使っている。
インスタンスのprototypeを設定するとオブジェクトへの参照をもつ
オブジェクトは他のオブジェクトへのリンクをもつようになる。(concatenative inheritance 連接継承)

A class is a blueprint.
A prototype is an object instance.

Aren’t classes the right way to create objects in JavaScript?
クラスがオブジェクトを作る正しい方法なの??
No

let animal = {
animalType : “brown”,
discribe (){
console.log(“fafa”)
}
}
これにprototpeに委譲させるObject.createを使って。

let animal = {
animalType : “brown”,
discribe (){
console.log(“fafa”)
}
}
let mouse = Object.assign(Object.create(animal), {animalType: ‘mouse’});
mouse.discribe()
//fafa
//mouseに別オブジェクト内のdiscribeメソッドがprototype委譲されている
//animalは「delegate prototype」となる

mose.animalType
//mouse
//自身のpropertyとして持っているのでprototypeチェーンを辿らない
JS Bin on jsbin.com

Object.createは
このまえやりました。
「we could attach delegate prototypes without using constructors and the `new` keyword」
この場合animalをnewとconstructorなしに、prototype委譲できる

「Don’t you need a constructor function to specify object instantiation behavior and handle object initialization?」
細かい初期設定や振る舞いを書くコンストラクターは必要ないってこと??

No

「Any function can create and return objects. When it’s not a constructor function, it’s called a factory function.」
どんな関数も作成、オブジェクトを返せる。それがコンストラクタではないとき、ファクトリー関数といわれる
JS Bin on jsbin.com

記事では
・privacy propertyのもち方
・new keywordが何をしているか
・instance of は嘘つきだ
・newはきもい!
・newを使うときとcreateではパフォーマンスに違いはあるのか
なども解説されています。
面白いし、英語記事から学ぶと英語とコードの勉強になって一石二鳥ですね。

でわまたーーー

【JavaScript】ClassをnewするとかObject.createでインスタンスを作らずprototype継承する外人を見つけた

 Why object literals in JavaScript are cool

なるほどなーっと思いましたーー。

でわまたーー。

【React】ブラウザ間の差異をなくすcore.jsをReact内にimportする方法〜ES6,ES7のメソッドを快適に使う〜

以前の記事でObject.assignがios8で使えなくてpolyfillを使った話をしたのですけど、
core-jsで解決できるようなので試してみた。
ES6でimportして実際使ってみるまでの記事です。

読み込む
npm i -D core-js

//React内に読み込む
使いたいオブジェクト名の階層までのパスを書きメソッドを読み込む

import { findIndex, fill } from 'core-js/library/fn/array/virtual';
import { includes }from 'core-js/library/fn/array/';
import { assign } from 'core-js/library/fn/object';

 const  HelloReact =  React.createClass({
  render() {
      console.log(Array(10)::fill(0).map((a, b) => b * b)::findIndex(it => it && !(it % 8)));
      var obj = {a: "fa"};
      console.log(assign({b: 'ooo'}, obj));
      var array = ["","faf"]
      console.log(array.includes("faf"));


    return (
    <div>
        <div>

////

【ES6】適当に試したり。正規表現とか

全コード


function getKey(k) {
  return `${k}`;
}

const obj = {
  id: 5,
  name: 'San Francisco',
  [getKey('enabled')]: true,
};

console.log(obj)
///////////////////////////


function f(x, ...y) {//ここで受け取らない分が配列の要素としてyになる
  // y is an Array
  console.log(y)//["hello","true"]
  return x * y.length;
}
const r1 = f(3, "hello", true) == 6
console.log(r1);//true

//////////////////////////////

function f(x, y, z, t, p) {//インデックス順に受け取る
  console.log(z);
  return x + y + z;
}
// Pass each elem of array as argument
//const arry = [1,2,3,5,6];
//f(...arry) == 6
//or
f(...[1,2,4]);


///////////////////////////////

let fibonacci = {
  [Symbol.iterator]() {
    let pre = 0, cur = 1;
    return {
      next() {
        console.log([pre, cur] = [cur, pre + cur]);
        return { done: false, value: cur }
      }
    }
  }
}

//////////////////////

let [a, b, c] = []
console.log(a,b,c);
typeof b

function getSomething(){
  return {
    first: 1,
    second: 2,
    third: 3
  }
}

var { first, second, third } = getSomething();
console.log(first)


console.log("repeat".repeat(2));

console.log(["morita","kenji","fafafa"].findIndex(x => x == "fafafa"))

console.log(["A","B","C"].map(x => Array.of(x)));

console.log(['a', 'b', 'c'].fill('kenji', 1, 2));

const i = [3, 0, 6, -1].find(x=> x < 0);
console.log(i)

function* idMaker(){
    var index = 0;
    while(true)
        yield index++;
}

const gen = idMaker();
console.log(gen)
////////////////////////////

const str = "わたしの名前は「もりた」です。あだなは「もりけん」です";

const re = /「.*?」/ig;


const myRe=/ken*/g;
const str2 = "fafakenfafkenji";
let array;
while ((array = myRe.exec(str2)) !== null) {
 let msg = array[0] + " を見つけました。";
  msg += "次のマッチは " + myRe.lastIndex + " からです。";
  console.log(msg);
}



const str3 = "<img src='fafa.com'>"
const str4 = "<p>"
const reg2 = /<(\S+)(\s+.+)?>/;
const reg3 = /<(?:\S+)(?:\s+.+)?>/;
const re2 = str3.match(reg2);
const re3 = str3.match(reg3);
const re4 = str4.match(reg2);
console.log(re2);console.log(re2[0]);
console.log(re3);console.log(re3[0]);
console.log(re4);console.log(re4[0]);


const str222 = "わたしの名前は「もりた」です。あだなは「もりけん」です";

const re222 = /「(.+?)」/ig;


let result;
while ((result = re222.exec(str222)) !== null){
  console.log(result[0],"ここ")
}

const nen = "西暦1980年の3581歳です";
const reg1 = /\d+(?=年)/;
console.log(nen.match(reg1))

const string3 = "washable reasonable accessible assemble answerable";
const reg5 = /\b\w+(?=able\b)/g;
console.log(string3.match(reg5));

const nen1 = "ケンジは昭和55年生まれの35歳であり、ケンジの母は昭和22年生まれの64歳である"
const reg6 = /\d+(?![年\d])/g;
console.log(nen1.match(reg6));

const str5 = "あの客はよく柿食う客だ";
const res5 =str5.match(/あの(.+)はよく柿食う\1だ/);
console.log(res5);

const tag = "<div><h1>kenjimorita.jp</h1></div>";

console.log(/<(\w+)><(\w+)>kenjimorita.jp<\/\2><\/\1>/.test(tag))

// const str6 = "西暦2010年は平成22年です。西暦1980年は昭和55年です。";
// console.log(str6.match(/(?<=昭和|平成)\d+/))

const str7 = "My name is Taro Suzuki and I am a researcher at ABC.";

console.log(str7.match(/\ba\w*\b/g));

var falseValue = new Boolean(false);
console.log(falseValue)//false



var fafa = null;
console.log(typeof fafa)//Object
console.log(fafa == undefined)//等値演算子ではtrueになってしまう
console.log(fafa === null);//true //同値演算子を使う

【ECMAScript2015(ES6)】後で猫に教えてあげたいES6の「Generators(ジェネレーター)とIterator(イテレータ)」

昨日はSymbol(シンボル)でしたが、今日はGeneratorsとIterator。
babel立ち上げてコード確認しながらやりました。

ジェネレータってなにかって再帰処理を簡単にしてくれるものなんですね。
そのイテレータオブジェクトを返す関数がジェネレータ

ジェネレータを扱うにはイテレータを理解する必要があるようです。
続きを読む

【React】babelでbabel-preset-stage-0や使う方法「ES7 Property Initialiazers for Default Props and Prop 」を使いたい方へ

英語文しかなかったので自分のようなReactにおいて「ES7 Property Initialiazers for Default Props and Prop」を使いたい方へ記事書きました

参照 http://babeljs.io/blog/2015/10/29/6.0.0 http://egorsmirnov.me/2015/06/14/react-and-es6-part2.html

babelは6系からそれぞれプラグインをインストールすることになったみたいです。

具体的には これらを適当にインストールしてください(適当です)

"babel-core": "^6.7.6",
"babel-loader": "^6.2.4",
"babel-plugin-syntax-class-properties": "^6.5.0",
"babel-plugin-transform-class-properties": "^6.6.0",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"babelify": "^6.1.3",

その後 package.jsonに下のようにpresetsを設定(使いたいpresetのプラグインです)上のならbebel-plugin-[ここ] 「ES7 Property Initialiazers for Default Props and Prop 」はstage-0として設定すればOK .babelrcだったらpackage.jsonと同じ階層に置けばいいみたいです。今回はjsonに記述します。

"babel": {
"presets" : ["es2015", "react", "stage-0"
 ]
},
"devDependencies": {
//some
}

で gulpfileのtransformのところに

.transform("babelify", {presets: ["es2015", "react", "stage-0"]})

でok

ちょっとエラーが出たり分からなかった場合下記リンク先に playgroundあげてありますので余計なソースを削って使ってください。 ミニマムでReact,ES6の最新が動作できるようにされています。

https://github.com/kenmori/React-ES6-Flux-Playground/tree/master/playground

【 併せて読みたい 】

【REACT】REACTの動きを理解したい人の為の最小サンプル

【REACT入門】過去のREACT初心者の自分にREACTのPROPSとSTATEの違いを簡単に説明してあげたい

【REACT × ES6 × FLUX】を手っ取り早く学びたい人の為にサンプル作ったよ【3の倍数と3が付くときだけ猫になるCOUNTER】

REACT × FLUX × ES6 [WIP]LINE風チャット

他のReact記事

フロントエンド記事

github

qiita

Tagged template strings(タグテンプレートストリング)

Tagged template strings(タグテンプレートストリング)が多分便利なので 理解したことを書いておく コードはコチラ

もしも下記のように呼び出した場合、

 tag'もりた${kenji}です' 

ES5でいうこのようなものとして呼び出している tag([“もりた”,”です”], kenji)

tagの第一引数に[“もりた”,”です”]という変数として展開されない文字列が要素となる配列を受け取る それ以外のkenjiは第二引数以降受け取れる。 上記が

tag’もりた${kenji}です${yeah}’ だとした場合 引数の数が増える

下記のように受け取った第一引数の配列のインデックスを参照することも可能(もちろん)

function tag(strings, …values){ console.log(strings[0]) //もりた console.log(strings1) //です }

具体的な使用例

var long = ’30px’; var weight = ’40px’;

function tag(strings, …values){ return m:${values[0]}、p:${values[1]}; };

var str1 = tag身長${long}で、体重は${weight}です;

console.log(str1);