-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathitem_45.js
More file actions
143 lines (106 loc) · 3.42 KB
/
item_45.js
File metadata and controls
143 lines (106 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// use 'hasOwnProperty' to protect against prototype pollution
// remember:
// "nick" in dict; // membership test
// dict.nick; // retrieval
// dict.son = 32; // update
// Even empty objects inherit properties from 'Object.prototype'
var dict = {};
"nick" in dict; // false
"son" in dict; //false
"kaigi" in dict; // false
"toString" in dict; // true
"valueOf" in dict; // true
// a better test for dictionary entries to avoid prototype pollution
dict.hasOwnProperty("nick"); // false
dict.hasOwnProperty("toString"); // false
dict.hasOwnProperty("valueOf"); // false
// we can also guard the lookup with a test
dict.hasOwnProperty("nick") ? dict.nick : undefined;
// dict.hasOwnProperty(x) ? dict[x] : undefined;
// what if we store an entry in the dictionary with the name "hasOwnProperty"
// then the prototype's method is no longer accessible
dict.hasOwnProperty = 10;
// dict.hasOwnProperty("nick"); error: dict.hasOwnProperty is not a function
// make no assumptions about 'hasOwnProperty'
var hasOwn = Object.prototype.hasOwnProperty;
// OR
var hasOwn = {}.hasOwnProperty;
hasOwn.call(dict, "nick");
// works even if the receiver has overridden its 'hasOwnProperty' method
var dict = {};
dict.nick = 16;
hasOwn.call(dict, "hasOwnProperty"); // false
hasOwn.call(dict, "nick"); // true
dict.hasOwnProperty = 10;
hasOwn.call(dict, "hasOwnProperty"); // true
hasOwn.call(dict, "nick"); // true
// avoid this boilerplate, abstract out this pattern
function Dict(elements) {
// allow an optional initial table
this.elements = elements || {}; // simple object
}
Dict.prototype.has = function(key) {
// own property only
return {}.hasOwnProperty.call(this.elements, key);
};
Dict.prototype.get = function(key) {
// own property only
return this.has(key) ? this.elements[key] : undefined;
};
Dict.prototype.set = function(key, val) {
this.elements[key] = val;
};
Dict.prototype.remove = function(key) {
delete this.elements[key];
};
var dict = new Dict({
nick: 16,
son: 32,
kaigi: 64
});
dict.has("nick"); // true
dict.get("son"); // 32
dict.has("valueOf"); // false
// '__proto__' can cause pollution problems
var empty = Object.create(null);
"__proto__" in empty; // false on my env
var hasOwn = {}.hasOwnProperty;
hasOwn.call(empty, "__proto__"); // false in my env
var dict = new Dict();
dict.has("__proto__"); // fasle in my env
// for max portability and safety
function Dict(elements) {
this.elements = elements || {};
this.hasSpecialProto = false; // has "__proto__" key?
this.specialProto = undefined; // "__proto__" element
}
Dict.prototype.has = function(key) {
if (key === "__proto__") {
return this.hasSpecialProto;
}
return {}.hasOwnProperty.call(this.elements, key);
};
Dict.prototype.get = function(key) {
if (key === "__proto__") {
return this.specialProto;
}
return this.has(key) ? this.elements[key] : undefined;
};
Dict.prototype.set = function(key, val) {
if (key === "__proto__") {
this.hasSpecialProto = true;
this.specialProto = val;
} else {
this.elements[key] = val;
}
};
Dict.prototype.remove = function(key) {
if (key === "__proto__") {
this.hasSpecialProto = false;
this.specialProto = undefined;
} else {
delete this.elements[key];
}
};
var dict = new Dict();
dict.has("__proto__"); // false