JavaScript の総復習
久しぶりに JavaScript を復習しようと思いました。
ポイントだけメモろうと思います。
このページの方針
・浅く、浅く、浅く
・const、let、varには触れない。もういいでしょ、これは。
・Map、Setは別のページで書いたので触れません。
JavaScript の世界に入るといつもの景色が違って見えます。
Strictモード
プログラムの先頭や関数の先頭に記述します。
'use strict'
分割代入
分割代入で変数の値を入れ替えられますが、1行目のセミコロンが無いとエラーになりました…セミコロン必要ですか…
let [a,b] = [1,2];
[a,b] = [b,a]
console.log(a,b)
プロパティのアクセス
プロパティへのアクセスはドットとブラケットの両方とも使えます。
const user = {id:'001',name:'もっさん'}
console.log( user.id,user.name )
console.log( user['id'],user['name'] )
プロトタイプ
function版
const User = function() {
this.name = 'もっさん'
}
User.prototype.getName = function(){
return this.name
}
const user = new User
console.log( user.getName() )
class版
class User {
name = 'もっさん'
}
User.prototype.getName = function(){
return this.name
}
const user = new User
console.log( user.getName() )
for of
for (let name of ['もっさん','ショコラ'])
console.log(name)
数値の桁区切りに _ を使うことができる。(Numeric separators)
これは PHP7.4以降 と同じですね。
console.log(100_000_000)
↓3桁以外の場所にも入れることができます。
バッククォートの中では、変数を展開することができる(→テンプレート文字列)。改行も普通にできる。
let name = 'Answorz!'
let str = `Hello
${name}`
console.log( str )
タグ付きテンプレート文字列。関数が呼び出せます。
const tag = (templates,name,age) => {
return `${templates[0]}${name}${templates[1]}${age}${templates[2]}`
}
const name = "もっさん"
const age = "40"
console.log(tag`私は${name}です。年齢は${age}です。`)
includesで配列の中の値を検索できるようになった。
ようするに $.inArray、indexOf。PHP では in_array。
['もっさん','ショコラ'].includes('もっさん')
atメソッドが追加され、配列、文字列の最後にアクセスし易くなった。
[0,1,2,3,4,5].at(-1)
'もっさん'.at(-1)
アロー関数内の this は、アロー関数が作られた場所の this を指す。
class Member {
name = 'もっさん'
constructor() {
setTimeout(() => console.log(this.name),3000)
}
}
new Member
…(スプレッド演算子)でリストの残りの値を変数に代入できる。
let [a,b,...other] = [1,2,3,4,5,6,7,8,9,10]
console.log(other)
??
PHPにもありますね。
let mossan
console.log(mossan ?? 'ショコラ') // ショコラ を出力
??=
PHPにもありますね。
let name
name ??= 'もっさん'
console.log(name) // もっさん を出力
let name = 'ショコラ'
name ??= 'もっさん'
console.log(name) // ショコラ を出力
||=
falsy の場合に代入します。
let name = false
name ||= 'もっさん'
console.log(name) // もっさん を出力
&&=
truthy の場合に代入します。
let name = 'ショコラ'
name &&= 'もっさん'
console.log(name) // もっさん を出力
?.(オプティカルチェーン)
参照先が null、undefined かを確認しないで、プロパティを取得したりメソッドを実行することができます。
PHP8.0 の「?->」ですね。
class User {
name = 'もっさん'
constructor() {
}
getName() {
return this.user?.name
}
}
const user = new User
console.log( user.getName() )
user.user = user;
console.log( user.getName() )
Symbol型
プライベートなアクセスに使えるようです。因みに、ES2022 でプライベートが使えるようになりました。
const id = Symbol()
const getBlodType = Symbol()
const name = 'name'
class User {
constructor() {
this[id] = '001'
this.name = 'もっさん'
console.log(this[getBlodType]()) // プライベートメソッドの呼び出し
}
getID() {
return this[id]
}
[getBlodType]() // プライベートメソッドの定義
{
return 'AB'
}
}
const user = new User
console.log(user.id);
console.log(user[id]);
console.log(user.name);
console.log(user[name]);
console.log(user.getID());
FetchAPI
WEB から HTML を取得するサンプルです。
fetch('http://www.yahoo.co.jp').then(res => res.text()).then(body => console.log(body))
Object.assign メソッド
オブジェクトにプロパティを追加することができます。
class User1 {
constructor(id,name) {
Object.assign(this,{id,name})
}
}
const user1 = new User1('0001','もっさん')
console.log(user1.id,user1.name)
const user2 = {}
Object.assign(user2 ,{id:'0002',name:'ショコラ'})
console.log(user2.id,user2.name)
Class プロパティ
constructor の中で this.なんとか でプロパティを定義する必要がなくなりました。
class User {
name = 'もっさん'
static foo = 'フー'
}
const user = new User
console.log(user.name) // もっさん を出力
console.log(User.foo) // フー を出力
Class staticイニシャライズブロック
staticブロックの中では this or User でアクセスすることができます。
class User {
static id
static name
static {
this.id = '001'
this.name = 'もっさん'
}
}
console.log(User.id,User.name)
Class []でプロパティ、メソッドの動的定義
ブラケット を使ってクラスにプロパティ、メソッドを動的に定義する例です。
let i = 0
class Members {
['data'+ ++i] = 'もっさん';
['getData'+ i]() {
return this.data1
}
['data'+ ++i] = 'ショコラ';
['getData'+ i]() {
return this.data2
}
}
const members = new Members
console.log(members.getData1())
console.log(members.getData2())
Class Private のものには頭に # を付ける。
最初、プライベートに # ってどうなんだろと思いましたが、ゲッター(get id())を作ってみたところ、すんなり書けました。もし # が無ければ、プロパティ名を別名にしなければならないのですが、頭に # をつけることで既に別名になっているんだ、と思いました。
class User {
#id = '001'
#getID() {
return this.#id
}
get id() {
return this.#getID()
}
}
const user = new User
console.log(user.id)
オブジェクトのプロパティの値を変数に入れる。
順不同でいけます。↓下の face には対応するプロパティが無いのでデフォルト値が入ります。no には対応するプロパティ id を入れることができます。
let {name,id,face='イケメン',id:no} = {id:'001',name:'もっさん'}
console.log(id,name,face,no)
変数でオブジェクトを作成
let {name,id,face='イケメン'} = {id:'001',name:'もっさん'}
let user = {id,name,face}
//let user2 = {user.id} // この形はできない。
console.log(user)
関数のプロパティに名前付き引数
const user = {id:'0001',name:'もっさん',face:'ポケモン'}
function getAll({id,name,face,blodType='AB'})
{
return id + name + face + blodType;
}
console.log( getAll(user) )
関数のデフォルト値に、関数に与えた引数 や 関数 も設定することができる。
function chocolat() {
return 'ショコラ';
}
function hello(a, b = a, c = chocolat()) {
console.log(a,b,c)
}
hello('もっさん')
Proxyクラス
new Proxy の 第1パラメータ にはインスタンスを与えます。
const id = Symbol
const name = 'name'
class User {
constructor() {
this[id] = '001'
this.name = 'もっさん'
}
getName() {
return this.name
}
}
const user = new Proxy(new User,{
get(target,prop,reciver) {
return target[prop]
},
set(target,prop,val,reciver) {
target[prop] = val
return true;
}
})
// テスト
console.log(user.id)
console.log(user[id])
user.name = 'ショコラ'
console.log(user.name)
console.log(user[name])
// メソッドをトラップしてみる。
console.log(user.getName())
user.getName = new Proxy(user.getName,{
apply(target,thisArg,argumentsList) {
let name = target.apply(thisArg,argumentsList)
return `[${name}]`
}
})
console.log(user.getName())
イテレーター
イテレーターの例。
class Members {
data = ['もっさん','ショコラ'];
[Symbol.iterator]() {
let i=0, that=this
return {
next:() => i < that.data.length ? {value: that.data[i++],done:false} : {done:true}
}
}
}
let members = new Members
for (let i=0; i<2; i++)
for (let name of members)
console.log(name)
ジェネレーター
ジェネレーターは function* で定義して yield で返す。yield* でジェネレーターや反復可能なオブジェクトに委任できます。
PHP のものとほぼ同じですね。
function*generator(id) {
id++
yield id+':もっさん'
id++
yield id+':ショコラ'
yield* generator2(id)
yield* (function*(id) {
id++
yield id+':もっさん3'
id++
yield id+':ショコラ3'
})(id)
}
function*generator2(id) {
id++
yield id+':もっさん2'
id++
yield id+':ショコラ2'
}
for (let i of generator(100)) {
console.log(i)
}
catch に(e)を書かなくてもOK。
PHP8.0以降 と同じ仕様ですね。
try {
throw new Error('err')
}
catch {
console.log('catch')
}
finally {
console.log('finally')
}
以上