我正在开发一个学习项目,该项目要求我实现一个递归函数,该函数将传入的对象进行字符串化,而不使用JSON.stringify。我必须将所有数据类型视为我的函数将接收的参数,虽然我很好,但是当传递数组/对象时我似乎感到困惑,并且我自己调用函数来迭代对象内容。 我做得不对,我所做的每一项改变都影响到我认为已经完成的其他领域,所以我的挫折感开始赢得这场战斗。我需要帮助的领域:
当我自己调用函数时,以与JSON.stringify
相同的方式输出数组/对象的所有元素。我看到的问题的一个示例是,如果我传递像["SO"]
这样的数组,我将返回[SO]
,但看起来我有这种可能性!
当函数作为参数传递时该怎么办,这是不允许的。
这是我到目前为止所拥有的。我感谢您提供的任何帮助。
var myJSONRecursiveFunc = function (obj) {
var stringed = "";
var result;
if (Number.isInteger(obj)) {
return "" + obj + "";
} else if (obj === null) {
return "" + null + "";
} else if (typeof obj === "boolean") {
return "" + obj + "";
} else if (typeof obj === "string") {
return '"' + obj + '"';
} else if (Array.isArray(obj)) {
if (obj.length === 0) {
return "[" + obj + "]";
}
for (var i = 0; i < obj.length; i++) {
if (Array.isArray(i)) {
myJSONRecursiveFunc(i);
} else {
stringed += "" + obj[i] + ""
}
}
return result = "[" + stringed + "]";
} else {
for (var val in obj) {
if (typeof val === "object") {
myJSONRecursiveFunc(val);
}
stringed += "" + val + "" + ":" + "" + obj[val] + "" + '';
}
return result = "{" + stringed + "}";
}
};
这还远非完美,因为我还在学习,所以请让我知道我可以改进的地方以及让它按原样工作的任何帮助。
答案 0 :(得分:1)
当我自己调用函数时,以与JSON.stringify相同的方式输出数组/对象的所有元素。我看到的问题的一个例子是,如果我传递像[&#34; SO&#34;]这样的数组,我正在返回[SO],但看起来我已经覆盖了这种可能性!
var val in obj
的递归仅传递val
,这是obj
的关键。您需要致电myJSONRecursiveFunc(obj[val])
才能获得正确的结果。此外,这适用于您的阵列。你的if语句需要检查obj[i]
是否是一个数组,而不是i
,它只是一个整数。在这种情况下,您需要说:
if (Array.isArray(obj[i])) {
myJSONRecursiveFunc(obj[i])
}
当函数作为参数传递时该怎么办,这是不允许的。
您需要检查传入的函数是否为typeof
函数,例如:if (typeof func === function)
这是一项非常有趣的练习。几个月前我做了这个,并且可以访问Underscore库。这是工作代码:
var stringifyJSON = function(obj) {
//Strings and null should be addressed here. Strings have quotes inside the string so I can't lump them together with booleans and numbers.
if (_.isString(obj)){
return '"' + obj.split('"').join('\\"') + '"';
}
if (_.isNull(obj)){
return 'null';
}
//Arrays get a temporary array that their stringified elements get pushed to, and then that temporary array is joined together and concatenated with the brackets that exist within the returned string.
if (_.isArray(obj)){
var tempArr = [];
_.each(obj, function(elem){
tempArr.push(stringifyJSON(elem));
});
return '[' + tempArr.join(',') + ']';
}
//Objects get a temporary string to add their stringified data to. Including a check for undefined values and function keys.
if (_.isObject(obj)){
var tempArr = [];
for (var k in obj){
if (_.isUndefined(obj[k]) || _.isFunction(k)){
return '{}';
} else {
tempArr.push(stringifyJSON(k) + ':' + stringifyJSON(obj[k]));
}
}
return '{' + tempArr.join(', ') + '}';
}
//Everything else = booleans, numbers
else {
return obj.toString();
}
};
答案 1 :(得分:1)
好的,让我们这样做。
function toJSON(obj) {
// There are people who will disagree with me
// but I think this variable is declared way too early.
// It's used in 2 places as a temp variable, so should
// be declared closer to where it's used.
// It should also be named more appropriately for how it's used.
// I used `arrayParts` and `keyValuePairs` instead.
var stringed = "";
// As far as I can tell, this variable is never actually
// used for anything useful.
// It's always `return result = <thing>`.
// If you're immediately returning, there's no need to save
// to a variable.
var result;
if (Number.isInteger(obj)) {
// The initial `"" + <number>` converts to a string.
// Appending another "" to the end is pointless in
// all of the below lines.
return "" + obj + "";
} else if (obj === null) {
return "" + null + "";
} else if (typeof obj === "boolean") {
return "" + obj + "";
} else if (typeof obj === "string") {
return '"' + obj + '"';
} else if (Array.isArray(obj)) {
// If the object is an array with length 0, you
// already know what it looks like.
// It's `[]`, so just return that instead of adding
// the empty array in the middle.
if (obj.length === 0) {
return "[" + obj + "]";
}
for (var i = 0; i < obj.length; i++) {
// In the top of this function, you handle all the
// different types of objects, so you should recurse and
// reuse that logic. Checking again here is wasted effort.
if (Array.isArray(i)) {
myJSONRecursiveFunc(i);
} else {
stringed += "" + obj[i] + ""
}
}
return result = "[" + stringed + "]";
// A better way to write this section would have
// looked like this.
// var arrayParts = []
// for( var i = 0; i < obj.length; i++ ){
// var stringifiedElement = toJSON( obj[ i ] )
// arrayParts.push( stringifiedElement )
// }
// return '[' + arrayParts.join( ',' ) + ']'
} else {
for (var val in obj) {
// Again, your function's start checks type and handles it.
// Use that recursively.
if (typeof val === "object") {
myJSONRecursiveFunc(val);
}
stringed += "" + val + "" + ":" + "" + obj[val] + "" + '';
}
return result = "{" + stringed + "}";
// This section could be rewritten as:
// var keyValuePairs = []
// for( var key in obj ){
// var pair = '"' + key + '":' + toJSON( obj[ key ] )
// keyValuePairs.push( pair )
// }
// return '{' + keyValuePairs.join( ',' ) + '}'
}
};
为了记录,当你将[&#39; SO&#39;]传入你的功能时,这就是正在发生的事情。 isArray
块首先捕获对象。
} else if( Array.isArray( obj ) ){
然后在你的循环中,else
块返回"" + obj[i] + ""
,转换为"" + "SO" + ""
,转换为"SO"
。
返回此内容后,"[" + "SO" + "]"
会变为"[SO]"
。
for (var i = 0; i < obj.length; i++) {
if (Array.isArray(i)) {
myJSONRecursiveFunc(i);
} else {
stringed += "" + obj[i] + "" // <-- the error
}
}
当你将obj作为接近结尾的实际对象循环时,你会这样做。
for( var val in obj ){
// foo
}
旁注:val
实际上是关键,因此有点误导。
这是Javascript的丑陋部分。如果修改了原始Object
,例如:Object.prototype.foobar = 5
,则'foobar':5
将显示在程序中的每个对象中。值得注意的是,只有非常确定他们正在做什么的开发人员应该这样做,但这是可能的。
要确保这不会破坏您的程序,请添加以下代码。
for( var key in obj ){
if( ! obj.hasOwnProperty( key ) ){
continue
}
}
obj.hasOwnProperty( <name> )
检查obj
是否有直接属性<name>
。如果没有,那么我们使用continue
跳转到下一个循环迭代。