未分類の覚書きです。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
参考