◆ DOMStringMap に remove とか delete の機能がなかった
◆ delete 演算子はプロパティを消すもの 変数は消えない
◆ delete で消せるプロパティかは プロパティの configurable 属性で決まる 

JavaScript には delete 演算子というものがあります

めったにというかほぼ使う機会がなくて このブログのコードでも探してみてもみつかりませんでした
実際には あるのは知っていても使ったことあったっけ?? ってくらいです

ホントに最初の JavaScript 使い始めたころは変数消したくて delete やって消えない! よくわからない!! とかあったような覚えもあります



そんな delete 演算子を使う機会が来たのでちょっと機能を紹介

delete は演算子

キーワードとか関数じゃなくて delete 演算子です
「!」 とか 「+」 と同じです
単語の演算子は他に new があります
delete value
delete obj.x
delete(obj.x)
delete fn()
delete 1
delete "abcd"
delete {a:1}

こんな書き方全部 おっけいです
注意:構文的に大丈夫というだけで実行しても何も消えないものが混ざっています

演算子なので関数みたいに
delete(100)

と書けますがこれは
!(a === b)

new(A.B)()

typeof({a:1})

void(0)

みたいなものです
関数呼びだしてるわけじゃないです
(new は一応関数実行してるけど new 関数じゃないですよね)

また演算子なので返り値があり それ自体が式となっています
console.log(delete 1)
// true

var obj = {key: 1, value: 2}
var fn = console.log.bind(console)

obj && delete obj.key && fn(obj)
// Object {value: 2}

こういうことができます

delete で消せるのはプロパティ

delete は変数を消すものではありません
オブジェクトからプロパティを消すものです

var obj = {a:1}
delete obj.a
console.log(obj)
// Object { }

!function(){
    var val = 1
    delete val
    console.log(val)
    // 1
}()

var value = "a"
delete value
consoel.log(value)
// "a"

グローバル変数でもローカル変数でも削除できません

消せるプロパティと消せないプロパティ

グローバル変数は window のプロパティですが消せません
しかし window.value = 1 の形式でプロパティを作った場合は消せます
window.aaa = 1
window.bbb = 2

delete window.aaa
delete bbb
console.log("aaa" in window)
// false

console.log("bbb" in window)
// false

aaa
// Uncaught ReferenceError: aaa is not defined

プロパティだと消せる理由は property descriptor の違いです

window.消せる = 1
var 消せない = 1
console.log("消せる", Object.getOwnPropertyDescriptor(window, "消せる"))
console.log("消せない", Object.getOwnPropertyDescriptor(window, "消せない"))
消せる   Object {value: 1, writable: true, enumerable: true, configurable: true}
消せない   Object {value: 1, writable: true, enumerable: true, configurable: false}

configurable が違いますね
var で宣言するか プロパティとして追加するかで configurable 属性が異なります

自分でこの設定のプロパティを作ってみます
Object.defineProperties(window, {
    消せるはず: {value: 1, writable: true, enumerable: true, configurable: true},
    消せないはず: {value: 1, writable: true, enumerable: true, configurable: false},
})

"消せるはず" in window
// true
"消せないはず" in window
// true

delete 消せるはず
delete 消せないはず

"消せるはず" in window
// false
"消せないはず" in window
// true

これは window だからということはなく他のプロパティも一緒です
var obj = {}
Object.defineProperties(obj, {
    can_delete: {value: 1, writable: true, enumerable: true, configurable: true},
    cannot_delete: {value: 1, writable: true, enumerable: true, configurable: false},
})
console.log(obj)

delete obj.can_delete
delete obj.cannot_delete

console.log(obj)
Object {can_delete: 1, cannot_delete: 1}
Object {cannot_delete: 1}

configurable

configurable 属性というのは プロパティを削除できるか です
true のプロパティは消せますが false のプロパティは消せません

また configurable という名前の通りで他の属性 (enumerable とか) の変更ができるか という設定も兼用しています
configurable が false なプロパティの enumerable を変えることはできません
もちろん configurable 自身も変えられません
var obj = {}
Object.defineProperty(obj, "a", {configurable: false})
Object.defineProperty(obj, "a", {configurable: true})
// Uncaught TypeError: Cannot redefine property: a
var obj = {}
Object.defineProperty(obj, "a", {configurable: true})

// configurable が true なのでここはできる
Object.defineProperty(obj, "a", {configurable: false})

// 一度 false にして true にしようとすると
Object.defineProperty(obj, "a", {configurable: true})
// Uncaught TypeError: Cannot redefine property: a

例外で writable だけは configurable が false でも true → false へ変更可能です
var obj = {}
Object.defineProperty(obj, "a", {configurable: false, writable: true})
Object.defineProperty(obj, "a", {writable: false})
// エラーなし
var obj = {}
Object.defineProperty(obj, "a", {configurable: false, writable: false})
Object.defineProperty(obj, "a", {writable: true})
// Uncaught TypeError: Cannot redefine property: a

使いたかった場所は……

今回なぜ delete が必要になったかというと DOMStringMap
document.body.dataset

などで取れる dataset のプロパティを消したかったのです

dataset は data-value="1" のような data-* の属性と対応しています
hidden などと同じように存在するかだけで判断して 値は見ない処理にしていたので必要なくなったら属性自体を削除するようにするつもりでした
dataset.value = ""

だと空文字になって属性は残ります

dataset 自体に remove メソッドがあってもいいと思うのですが ありませんでした

調べてみると delete 演算子で消すことが多いようだったので久々の delete 使うことになりました



まあ 最後には
document.body.removeAttribute("data-value")

という方法にして delete 演算子はコードの中からきえてしまった んですけどね