2017年2月19日日曜日

コンストラクタ別クローン作成用関数

String, Number, Boolean, Date, RegExp, Functionなどを引数として与えるとそのクローンを返すという関数を作成しました。




今回は動作確認用にgetCloneという関数をグローバル領域に作成しましたが、用途・目的としてはsetProp以外から呼び出すことは無さそうな気がするのでsetPropからしか呼べない(グローバル領域を汚さない)ようにしようか検討中。。

以下ソース
<job>
<script>
getClone=function(){
var gt=function(obj){return typeof(obj)}
var gc=function(obj){return obj.constructor}
var objT={}
objT[gt('')] = objT[gt(0)] = objT[gt(true)] = objT[gt(objT.und)] = true
var objC={}
objC[gc({})] = function(obj,swSub){return setProp({}, obj, swSub)}
objC[gc([])] = function(obj,swSub){return setProp([], obj, swSub)}
objC[gc(/1/)] = function(obj){var re; eval('re = '+obj); return re}
objC[gc(new Date())] = function(obj){return new Date(obj+'')}
objC[gc(gc)] = function(obj,swSub){var f; eval('f = '+obj); return setProp(f, obj, swSub)}
return function(obj, swSub){ return (objT[gt(obj)] || obj===null) ? obj : objC[gc(obj)](obj, swSub) }
}()
forIn = function(obj,fun){var name,res; for(name in obj){if(res=fun(name, obj[name])){return res}}}
setProp=function(objTarget, objProp, swSub, swValue){
var funChildsCheck=function(){return true}
var arrT=[], arrP=[], 階層=-1, arrC=[].constructor
var fun=function(n,v){
if(swSub && forIn(v,funChildsCheck)){
fun0(arrT[階層][n] || (arrT[階層][n]=getClone(v)), v)
return
}
if(swValue && !v){return}
arrT[階層][n] = v
}
var fun0=function(objT, objP){
arrT.push(objT)
arrP.push(objP)
階層++
forIn(objP, fun)
階層--
arrT.pop()
arrP.pop()
}
fun0(objTarget, objProp)
return objTarget
}
WScript.Echo(typeof(true)+'\n\n'+getClone(true))
obj0 = {a:1, b:2}
obj1 = getClone(obj0)
obj1.a = 3
// obj0.a:1
WScript.Echo('obj0.a:'+obj0.a)
// obj1.a:3
WScript.Echo('obj1.a:'+obj1.a)
arr0 = [1,2,3]
arr1 = getClone(arr0)
// arr1.length:3
WScript.Echo('arr1.length:'+arr1.length)
dat0 = new Date('2016/12/25 00:11:22')
dat1 = getClone(dat0)
// dat1:Sun Dec 25 00:11:22 UTC+0900 2016
WScript.Echo('dat1:'+dat1)
fun0 = function(){ WScript.Echo(arguments.callee.num) }
fun0.num = 123
fun1 = getClone(fun0)
fun1.num = 456
// 123
fun0()
// 456
fun1()
if(0){
var un={}
// error un.a.constructorはNullまたはオブジェクトではありません
// WScript.Echo(un.a.constructor)
WScript.Echo(null)
// null.constructorはNullまたはオブジェクトではありません
// WScript.Echo(null.constructor)
// boolean
WScript.Echo(typeof(true))
// object
WScript.Echo(typeof(null))
// undefined
WScript.Echo(typeof(un.a))
// string
WScript.Echo(typeof(''))
// string
WScript.Echo(typeof('str'))
// number
WScript.Echo(typeof(0))
// /1/g
WScript.Echo(/1/g)
// Wed Feb 15 16:45:23 UTC+0900 2017
var d=new Date()
WScript.Echo([d, new Date(d+'')].join('\n'))
}
</script>
</job>


Mathが対象になるケースはないだろう、とかDate、RegExpオブジェクトにプロパティを追加することはないだろう、という予想で上記のようにしていますが、もし必要ならobjC[gc(/1/)]などの中でもsetPropを呼ぶように変更すればOK。

0 件のコメント:

コメントを投稿