LoginSignup
0
0

More than 3 years have passed since last update.

JavaScript 未分類の覚書き

Last updated at Posted at 2020-07-29

未分類の覚書きです。Mapや配列関係のものは別に投稿しています。

オブジェクトリテラルで配列の長さを指定して作成する

Array.fromは1番目の引数にオブジェクトリテラル{length: 要素数}を指定できます。2番目の引数mapFnと組み合わせることで一時的な配列を作成せずに指定長の配列を作成できます。

Array.from({length: 100})
// (100) [undefined, undefined, ..., undefined]

Array.from({length: 100}, (_, i) => i)
// (100) [0, 1, ..., 98, 99]

Array.from({length: 100}, (_, i) => 2 + i * 2)
// (100) [2, 4, ..., 198, 200]

動作確認環境:Google Chrome 84.0.4147.105(Windows、64 ビット)

関数がnew演算子で呼び出されたか判断する

function内部でnew.targetを呼び出すとnew演算子で呼び出されたか判断できます。

function f1()
{
    console.log(`this: ${this}, new.target: ${new.target}`);
}
// new演算子なしで呼び出すとthis == グローバルオブジェクト、new.target == undefined
f1();
// this: [object Window], new.target: undefined

// new演算子ありで呼び出すとthis == 新しいインスタンス、new.target == コンストラクタや関数への参照
new f1();
// this: [object Object], new.target: function f1()
// {
//     console.log(`this: ${this}, new.target: ${new.target}`);
// }

動作確認環境:Google Chrome 84.0.4147.105(Windows、64 ビット)

関数はnew演算子の有無でthisの値と省略時の戻り値が異なる

function f1()
{
    this.a = 1;
    this.b = 2;
}
// 新しいインスタンスを作成してそのフィールドa、bに値を代入する。
t = new f1();
// thisに代入したのでグローバル変数a、bは存在しません。
console.log(`global: a=${a}, b=${b}`); // Uncaught ReferenceError: a is not defined
// newで呼び出した関数はreturnの省略時にthisを返します。
console.log(`f1: a=${t.a}, b=${t.b}`); // f1: a=1, b=2
delete a;
delete b;

// 関数f1を呼び出してグローバル変数a、bに値を代入する。
t = f1();
// newが指定されていないのでthisはグローバル変数を指します。
// したがってグローバル変数a、bが作成されます。
console.log(`global: a=${a}, b=${b}`); // global: a=1, b=2
// newなしで呼び出した関数はreturnの省略時にundefinedを返します。
console.log(`f1: a=${t.a}, b=${t.b}`); // Uncaught TypeError: t is undefined

Array関数はArrayコンストラクタ(new Array)として振る舞う

Array関数はnew Arrayと同様の機能を提供します。これはArray関数の特別な振る舞いであり、通常はnew演算子の有無で動作が変わることに注意してください。

Array型の@@iteratorメソッドの別名

const array1 = [0, 1, 2];
array1[Symbol.iterator] === array1.values; // true

仕様です。Array.prototype[@@iterator]() - JavaScript | MDN

イテラブル、イテレーター、イテレーターリザルトの判定

// オブジェクトがイテレータのプロトコルを実装するか判断します。
const implementsIterable = (obj) => obj && obj[Symbol.iterator] instanceof Function && obj[Symbol.iterator].length == 0;
//  オブジェクトがイテラブルのプロトコルを実装するか判断します。
const implementsIterator = (obj) => obj?.next instanceof Function && obj.next.length == 0;
// オブジェクトがイテレーターリザルトのプロトコルを実装するか判断します。
const implementsIteratorResult = (obj) => obj && "value" in obj && typeof obj.done === "boolean";

const array1  = [0, 1, 2];
const iter1   = array1[Symbol.iterator]();
const result1 = iter1.next();

console.log(implementsIterable(array1));  // true
console.log(implementsIterable(iter1));   // true
console.log(implementsIterable(result1)); // false

console.log(implementsIterator(array1));  // false
console.log(implementsIterator(iter1));   // true
console.log(implementsIterator(result1)); // false

console.log(implementsIteratorResult(array1));  // false
console.log(implementsIteratorResult(iter1));   // false
console.log(implementsIteratorResult(result1)); // true

参考
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/in
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Iteration_protocols

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0