Created
May 9, 2017 13:01
-
-
Save tasogare3710/20ec55b5e1be2122c611591994e4d023 to your computer and use it in GitHub Desktop.
ClassDeclarationを使わずにArrayのsubtypeを作る。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function A(...args) { | |
// 厳密に書くと... | |
// | |
// const value = Reflect.construct(Array, args, A) | |
// if(new.target !== undefined) { | |
// this = value | |
// } else { | |
// return value; | |
// } | |
// | |
// となるが、es5からthisへの代入が禁止されたため、returnするしかなくなり、 | |
// 分岐が無駄になるので最適化する。 | |
return Reflect.construct(Array, args, A) | |
} | |
Reflect.defineProperty(A, Symbol.species, { get: function(){ return this } }) | |
A.prototype = { | |
__proto__: [], | |
constructor: A, | |
pop: function(){ | |
console.log("loging: pop") | |
return Array.prototype.pop.call(this) | |
}, | |
push: function(...args){ | |
console.log("loging: push") | |
return Array.prototype.push.call(this, ...args) | |
}, | |
} | |
// - - - | |
function assert(expr, thrower=function(e){ throw new TypeError(`assertion: unexpected ${e}`) }) { | |
if(expr === false){ | |
thrower(expr) | |
} | |
} | |
function assertSome(a, b, thrower=function(x, y){ throw new TypeError(`assertion: unexpected ${x} is ${y}`) }) { | |
if(!Object.is(a, b)) { | |
thrower(a, b) | |
} | |
} | |
function assertOwnDeep(a, b, thrower=function(x, y){ throw new TypeError(`assertion: unexpected ${x} is ${y}`) }) { | |
for(const [k, v] of Object.entries(a)) { | |
if (b.hasOwnProperty(k)) { | |
assertSome(v, b[k], thrower) | |
} else { | |
thrower(a,b) | |
} | |
} | |
} | |
assert(new A instanceof Array) | |
assert(Array.isArray(new A)) | |
assert(A.prototype.length === 0) | |
var a = new A | |
a.push(3,2,1) | |
assertOwnDeep([3, 2, 1], a) | |
a.pop() | |
assertOwnDeep([3, 2], a) | |
var b = Array.of.call(A, 1,2,3) | |
assert(b.constructor === A) | |
var c = Array.from.call(A, [1,2,3]) | |
assert(c.constructor === A) | |
var d = A(1,2,3) | |
assertOwnDeep([1,2,3], d) | |
assert(d.constructor === A) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment