Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

实现一个 JSON.stringify #39

Open
YvetteLau opened this issue Jul 1, 2019 · 9 comments
Open

实现一个 JSON.stringify #39

YvetteLau opened this issue Jul 1, 2019 · 9 comments

Comments

@YvetteLau
Copy link
Owner

No description provided.

@tpxiang
Copy link

tpxiang commented Jul 1, 2019

JSON.stringify是浏览器高版本带的一个将JS的Objtect对象转换为JSON字符串的一个方法JSON.stringify
的一些 规则以及注意点:当对象为number,null,boolean的时候,直接转换为相应的字符串就可以了。但是 string,function,undefined,object,array等,都需要特殊处理。

1.undefined,该类型使用JSON.stringify处理的时候,如果对象就是undefined,将会输出"undefined",如果
对象是数组的元素,那么将会变成null,比如:[undefined],stringify之后变成了"[null]";如果该对象是object
的元素,那么该属性将当作不存在,不输出,比如{a:1,b:undefined},stringify之后是"{"a":1},B属性直接
被抛弃。

2.字符串在拼接的时候需要把内部的双引号处理掉
//JSON.stringify的主函数

var simpleTypes = ["number", "boolean", "undefined", "string", "function"];  
function stringify(object){  
    var type = typeof object;  
    //如果是简单类型,则直接返回简单类型的结果  
    if(indexOf(simpleTypes, type) > -1){  
        return parseSimpleObject(object);  
    }  
    //数组对象
    if(object instanceof Array){  
        var len = object.length;  
        var resArr = [];  
        for(var i = 0; i < len; i++){  
            var itemType = typeof object[i];  
            if(indexOf(simpleTypes, itemType) > -1){  
                //undefined特殊处理,数组中变成null  
                if(itemType !=  "undefined"){  
                    resArr.push(parseSimpleObject(object[i]));  
                }else{  
                    resArr.push("null");  
                }     
            }else{  
                //递归处理JS数组中的复杂元素  
                resArr.push(stringify(object[i]));  
            }  
        }  
        return "[" + resArr.join(",") + "]";  
    }  
      
    //普通的object对象  
    if(object instanceof Object){  
        if(object == null){  
            return "null";  
        }  
        var resArr = [];    
        for(var name in object){  
            var itemType = typeof object[name];  
            if(indexOf(simpleTypes, itemType) > -1){  
                //undefined特殊处理,object中不编码  
                if(itemType !=  "undefined"){  
                    resArr.push("\"" + name + "\":" + parseSimpleObject(object[name]));      
                }  
            }else{  
                resArr.push("\"" + name + "\":" + stringify(object[name]));  
            }  
        }  
        return "{" + resArr.join(",") + "}";  
    }  
}  

@clark-maybe
Copy link

clark-maybe commented Jul 1, 2019

JSON.stringify(value[,replacer[,space]]):

Boolean|Number|String 类型会自动转换成对应的原始值。

undefined、任意函数以及 symbol,会被忽略(出现在非数组对象的属性值中时),或者被转换成 null(出现在数组中时)。

不可枚举的属性会被忽略

如果一个对象的属性值通过某种间接的方式指回该对象本身,即循环引用,属性也会被忽略。

function jsonStringify(obj){
        let type = typeof obj;
        if(type !== 'object' || type === null){
            if(/string|undefined|function/.test(type)){
                obj = '"' + obj + '"';
            }
            return String(obj);
        }else{
            let json = [];
            arr = (obj && obj.constructor === Array);
                for(let k in obj){
                    let v = obj[k];
                    let type = typeof v;
                    if(/string|undefined|function/.test(type)){
                        v = '"' + v + '"';
                    }else if(type === 'object'){
                        v = jsonStringify(v);
                    }
                    json.push((arr ? "" : '"' + k + '":') + String(v));
                }
                return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
            }
    }

    console.log(jsonStringify({x: 5, y: 12, t:{a: 5}}));//{"x":5,"y":12,"t":{"a":5}}

摘抄自 鱼头大佬的公众号 -- '鱼头的Web海洋'

顺便抢沙发,哈哈

沙发没了 - -

@KRISACHAN
Copy link

今天的题目不现实。。。JS一共有284种标准内置对象。。。事实上它们stringify出来不都是一样的

      Object.prototype.types = function () {
        var toString = Object.prototype.toString
        var map = {
          '[object Boolean]': 'boolean',
          '[object Number]': 'number',
          '[object String]': 'string',
          '[object Function]': 'function',
          '[object Array]': 'array',
          '[object Date]': 'date',
          '[object RegExp]': 'regExp',
          '[object Undefined]': 'undefined',
          '[object Null]': 'null',
          '[object Object]': 'object',
          '[object Arguments]': 'arguments',
          '[object Error]': 'error',
          '[object Window]': 'window',
          '[object HTMLDocument]': 'document',
        };
        var el = this instanceof Element ? 'element' : map[toString.call(this)];
        return el
      }

      Object.prototype.stfy = function () {
        const type = this.types()
        const typeObj = {
          'boolean': data => '' + !!data,
          'number': data => data + '',
          'string': data => `"${data}"`,
          'function': data => undefined,
          'array': data => {
            let res = '['
            for (let i = 0, len = data.length; i < len; ++i) {
              let cur = data[i].stfy()
              res += (cur)
            }
            res += ']'
            return res
          },
          'date': data => data.toJSON(),
          'regExp': data => '{}',
          'undefined': data => 'undefined',
          'null': data => 'null',
          'object': data => {
            let res = '{'
            for (let key in data) {
              if (data.hasOwnProperty(key)) {
                let cur = data[key].stfy()
                if (cur) {
                  res += `"${key}:${cur}"`
                }
              }
            }
            res += '}'
            return res
          },
          'arguments': data => {
            let res = '{'
            for (let i = 0, len = data.length; i < len; ++i) {
              let cur = `"${i}:${data[i]}${(i === len - 1) ? '' : ','}"`
            }
            res += '}'
            return res
          },
          'error': data => '{}',
          'window': data => new Error('Converting circular structure to JSON'),
          'document': data => '{}',
        }
        if (typeObj[type]) {
          return typeObj[type](this)
        } else {
          console.log('嘤嘤嘤,内置对象太多,写不过来')
          return JSON.stringify(this)
        }
      }

@darlingyz
Copy link

JSON.stringify会处理的几种类型: String, Number, Boolean, null, Array, Object
不会处理的几种类型: Date, RegExp, undefined, Function
语法:
JSON.stringify(value[, replacer[, space]])
参数说明:
value:
必需, 要转换的 JavaScript 值(通常为对象或数组)。

replacer:
可选。用于转换结果的函数或数组。

如果 replacer 为函数,则 JSON.stringify 将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined,则排除成员。根对象的键是一个空字符串:""。

如果 replacer 是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。

space:
可选,文本添加缩进、空格和换行符,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。

----还是学习大佬们写的方法吧

@Yuko7245
Copy link

Yuko7245 commented Jul 1, 2019

JSON.stringify是浏览器高版本带的一个将JS的Objtect对象转换为JSON字符串的一个方法JSON.stringify
的一些 规则以及注意点:当对象为number,null,boolean的时候,直接转换为相应的字符串就可以了。但是 string,function,undefined,object,array等,都需要特殊处理。

1.undefined,该类型使用JSON.stringify处理的时候,如果对象就是undefined,将会输出"undefined",如果
对象是数组的元素,那么将会变成null,比如:[undefined],stringify之后变成了"[null]";如果该对象是object
的元素,那么该属性将当作不存在,不输出,比如{a:1,b:undefined},stringify之后是"{"a":1},B属性直接
被抛弃。

2.字符串在拼接的时候需要把内部的双引号处理掉

if (!window.JSON) {
    window.JSON = {
        parse: function(jsonStr) {
            return eval('(' + jsonStr + ')');
        },
        stringify: function(jsonObj) {
            var result = '',
                curVal;
            if (jsonObj === null) {
                return String(jsonObj);
            }
            switch (typeof jsonObj) {
                case 'number':
                case 'boolean':
                    return String(jsonObj);
                case 'string':
                    return '"' + jsonObj + '"';
                case 'undefined':
                case 'function':
                    return undefined;
            }

            switch (Object.prototype.toString.call(jsonObj)) {
                case '[object Array]':
                    result += '[';
                    for (var i = 0, len = jsonObj.length; i < len; i++) {
                        curVal = JSON.stringify(jsonObj[i]);
                        result += (curVal === undefined ? null : curVal) + ",";
                    }
                    if (result !== '[') {
                        result = result.slice(0, -1);
                    }
                    result += ']';
                    return result;
                case '[object Date]':
                    return '"' + (jsonObj.toJSON ? jsonObj.toJSON() : jsonObj.toString()) + '"';
                case '[object RegExp]':
                    return "{}";
                case '[object Object]':
                    result += '{';
                    for (i in jsonObj) {
                        if (jsonObj.hasOwnProperty(i)) {
                            curVal = JSON.stringify(jsonObj[i]);
                            if (curVal !== undefined) {
                                result += '"' + i + '":' + curVal + ',';
                            }
                        }
                    }
                    if (result !== '{') {
                        result = result.slice(0, -1);
                    }
                    result += '}';
                    return result;

                case '[object String]':
                    return '"' + jsonObj.toString() + '"';
                case '[object Number]':
                case '[object Boolean]':
                    return jsonObj.toString();
            }
        }
    };
}

@YvetteLau
Copy link
Owner Author

JSON.stringify 功能

JSON.stringify([, replacer [, space]) 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串。此处模拟实现,不考虑可选的第二个参数 replacer 和第三个参数 space,如果对这两个参数的作用还不了解,建议阅读 MDN 文档。

  1. 基本数据类型:

    • undefined 转换之后仍是 undefined(类型也是 undefined)
    • boolean 值转换之后是字符串 "false"/"true"
    • number 类型(除了 NaNInfinity)转换之后是字符串类型的数值
    • symbol 转换之后是 undefined
    • null 转换之后是字符串 "null"
    • string 转换之后仍是string
    • NaNInfinity 转换之后是字符串 "null"
  2. 如果是函数类型

    • 转换之后是 undefined
  3. 如果是对象类型(非函数)

    • 如果是一个数组

      • 如果属性值中出现了 undefined、任意的函数以及 symbol,转换成字符串 "null"
    • 如果是 RegExp 对象。
      返回 {} (类型是 string)

    • 如果是 Date 对象,返回 DatetoJSON 字符串值

    • 如果是普通对象;

      • 如果有 toJSON() 方法,那么序列化 toJSON() 的返回值。
      • 如果属性值中出现了 undefined、任意的函数以及 symbol 值,忽略。
      • 所有以 symbol 为属性键的属性都会被完全忽略掉。
  4. 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。

模拟实现(待优化)

function jsonStringify(data) {
    let dataType = typeof data;
    
    if (dataType !== 'object') {
        let result = data;
        //data 可能是 string/number/null/undefined/boolean
        if (Number.isNaN(data) || data === Infinity) {
            //NaN 和 Infinity 序列化返回 "null"
            result = "null";
        } else if (dataType === 'function' || dataType === 'undefined' || dataType === 'symbol') {
            //function 、undefined 、symbol 序列化返回 undefined
            return undefined;
        } else if (dataType === 'string') {
            result = '"' + data + '"';
        }
        //boolean 返回 String()
        return String(result);
    } else if (dataType === 'object') {
        if (data === null) {
            return "null"
        } else if (data.toJSON && typeof data.toJSON === 'function') {
            return jsonStringify(data.toJSON());
        } else if (data instanceof Array) {
            let result = [];
            //如果是数组
            //toJSON 方法可以存在于原型链中
            data.forEach((item, index) => {
                if (typeof item === 'undefined' || typeof item === 'function' || typeof item === 'symbol') {
                    result[index] = "null";
                } else {
                    result[index] = jsonStringify(item);
                }
            });
            result = "[" + result + "]";
            return result.replace(/'/g, '"');
            
        } else {
            //普通对象
            /**
             * 循环引用抛错(暂未检测,循环引用时,堆栈溢出)
             * symbol key 忽略
             * undefined、函数、symbol 为属性值,被忽略
             */
            let result = [];
            Object.keys(data).forEach((item, index) => {
                if (typeof item !== 'symbol') {
                    //key 如果是symbol对象,忽略
                    if (data[item] !== undefined && typeof data[item] !== 'function'
                        && typeof data[item] !== 'symbol') {
                        //键值如果是 undefined、函数、symbol 为属性值,忽略
                        result.push('"' + item + '"' + ":" + jsonStringify(data[item]));
                    }
                }
            });
            return ("{" + result + "}").replace(/'/g, '"');
        }
    }
}

测试代码

let sym = Symbol(10);
console.log(jsonStringify(sym) === JSON.stringify(sym));
let nul = null;
console.log(jsonStringify(nul) === JSON.stringify(nul));
let und = undefined;
console.log(jsonStringify(undefined) === JSON.stringify(undefined));
let boo = false;
console.log(jsonStringify(boo) === JSON.stringify(boo));
let nan = NaN;
console.log(jsonStringify(nan) === JSON.stringify(nan));
let inf = Infinity;
console.log(jsonStringify(Infinity) === JSON.stringify(Infinity));
let str = "hello";
console.log(jsonStringify(str) === JSON.stringify(str));
let reg = new RegExp("\w");
console.log(jsonStringify(reg) === JSON.stringify(reg));
let date = new Date();
console.log(jsonStringify(date) === JSON.stringify(date));
let obj = {
    name: '刘小夕',
    age: 22,
    hobbie: ['coding', 'writing'],
    date: new Date(),
    unq: Symbol(10),
    sayHello: function() {
        console.log("hello")
    },
    more: {
        brother: 'Star',
        age: 20,
        hobbie: [null],
        info: {
            money: undefined,
            job: null,
            others: []
        }
    }
}
console.log(jsonStringify(obj) === JSON.stringify(obj));


function SuperType(name, age) {
    this.name = name;
    this.age = age;
}
let per = new SuperType('小姐姐', 20);
console.log(jsonStringify(per) === JSON.stringify(per));

function SubType(info) {
    this.info = info;
}
SubType.prototype.toJSON = function() {
    return {
        name: '钱钱钱',
        mount: 'many',
        say: function() {
            console.log('我偏不说!');
        },
        more: null,
        reg: new RegExp("\w")
    }
}
let sub = new SubType('hi');
console.log(jsonStringify(sub) === JSON.stringify(sub));
let map = new Map();
map.set('name', '小姐姐');
console.log(jsonStringify(map) === JSON.stringify(map));
let set = new Set([1,2,3,4,5,1,2,3]);
console.log(jsonStringify(set) === JSON.stringify(set));

@jodiezhang
Copy link

jodiezhang commented Jul 6, 2019

粗略的翻译了一下,实例参考小姐姐
24.3.2 JSON.stringify(value[,replacer[,space]])

stringify函数返回一个代表ECMAScript值的,以UTF-16编码的,JSON格式的字符串。
可以接受3个参数。
value参数是一个ECMAScript值,通常是一个对象或者数组,尽管它可以是一个String,Boolean,Number或者null。
可选参数replacer可以是一个函数,改变对象和数组序列化的方式,也可以是一个字符串和数字对象的数组,这个数组作为一个白名单用来筛选需要被序列化的对象的属性名。
可选参数space是一个String或者Number,用来允许在序列化的结果中插入空间来提高可读性。

下面是序列化一个对象的步骤

1.使stack是一个空的list
2.使indent是一个空的String
3.使PropertyList和ReplacerFunction是undefined
4.如果Type(replacer)是一个对象,那么
     a.如果IsCallable(replacer)是true,那么
            i.把replacer给ReplacerFunction
     b.否则,
            i. 赋值IsArray(replacer)给isArray
           ii. ReturnIfAbrupt(isArray)
          iii. 如果isArray是true,那么
               1. 使PropertyList为一个空的list
               2. ToLength(Get(replacer, "length"))赋值给len
               3. ReturnIfAbrupt(len)
               4. 赋值k为0
               5. 如果k小于len继续重复
                      a. 赋值Get(replacer,ToString(k))给v
                      b. ReturnIfAbrupt(v)
                      c.  是item变量为undefined
                      d. 如果Type(v)是String使item等于v
                      e. 否则 如果Type(v) 是Number,使得item为ToString(v)
                      f.  否则如果Type(v)是Object那么
                                 i.如果v有[[StringData]]或者[[NumberData]]内部插槽,使得item为ToString(v)
                                ii. ReturnIfAbrupt(item)
                      g. 如果item不是undefined并且item不是PropertyList中的一员,那么 
                                i. 把item 放到PropertyList中去
                      h. 使得k=k+1
5. 如果Type(space) 是一个对象,那么
     a.  如果space有[[NumberData]]内部插槽,那么
            i. 使得space等于ToNumber(space)
           ii. ReturnIfAbrupt(space)
     b. 否则如果 space 有[[StringData]]内部插槽,那么
           i. 使得space为ToString(space)
          ii. ReturnIfAbrupt(space)
6. 如果Type(space)是一个Number,那么
            a. 使得space为min[10,ToInteger(space)]
            b. 为一个包含了code 0x0020(space)的String设置gap
                如果space小于1那么这个gap被设置为空字符串
7. 否则,如果Type(space) 是一个String
            a.如果String中元素的数目是10或者更少,gap被设置为一个space否则被设置为space的头10个元素
8. 否则
            a. 设置gap为空字符串
9. 使得wrapper等于ObjectCreate(%ObjectPrototype%)
10. 使得status等于CreateDataProperty(wrapper,the empty String,value)
11. Assert: status is true
12. 返回SerialJSONProperty(the empty string,wrapper)
**Note1** JSON结构可以允许任何深度的嵌套,但是他们必须为非循环的,如果value是或者包含一个循环的结构,那么stringify必须抛出一个TypeError异常。下面是一个不能被stringify的例子
a=[]
a[0]=a
my_text= JSON.stringify(a);//会报TypeError异常
**Note2**  符号原始值
null  在JSON 中展示为 String null
undefinded 被忽略
true 在JSON中被展示为String true
false 在JSON中被展示为String false
**Note3** String值被包含在引号中,“和\通过加前缀\进行escape
\b (BACKSPACE), \f (FORM FEED), \n (LINE FEED), \r (CARRIAGE RETURN), \t (CHARACTER TABULATION).
**Note4**  有限的数字如ToString(number)被调用一样被序列化。NaN和无限数都被序列化成null
**Note5**  对于没有JSON表现的value(如undefined和function)不会产生一个String,相反他们会生成一个
undefined value.在数组中,这样的值会变成String null。在对象中,会直接忽略
**Note6** 一个对象被渲染成,一个左花括号,后面0个或者一个以逗号分隔的属性,然后由花括号结尾,一个属性是一个被引号括起来的字符串代表属性名,然后是冒号,然后是序列化的属性值。一个数组被渲染成,一个左方括号,然后是0个或者更多的值,通过逗号分隔开,然后以右方括号结尾
24.3.2.1  运行时语义:SerializeJSONProperty(key,holder)
    key和holder可以访问ReplaceFunction
    1. 使得value=Get(holder,key)
    2. ReturnIfAbrupt(value)
    3. 如果Type(value)是一个对象,那么,
              a. 使得toJSON=Get(value,"toJSON")
              b. ReturnIfAbrupt(value)
              c.  如果IsCallable(toJSON)为true
                        i. 使得value=Call(toJSON,value,<key>)
                       ii. ReturnIfAbrupt(value)
    4. 如果ReplacerFunction不为undefined那么
              a. let value=Call(ReplacerFunction,holder,<key,value>)
              b. ReturnIfAbrupt(value)
    5. 如果Type(value)是对象,那么
              a.如果value有[[NumberData]]内部插槽,那么,
                           i.使得value=ToNumber(value)
                          ii.returnIfAbrupt(value)
               b.否则如果,value有一个[[StringData]]内部插槽,那么,
                          i. 使得value=ToString(value)
                         ii. ReturnIfAbrupt(value)
               c.否则如果,value有一个[[BooleanData]]内部插槽,那么,
                          i.使得value=这个value的[[BooleanData]]内部插槽的值
   6. 如果value为null 返回"null"
   7. 如果value为true,返回"true"
   8. 如果value为false,返回"false"
   9. 如果Type(value)为String,那么返回QuoteJSONString(value)
  10. 如果Type(value)为Number,那么,
        a. 如果值为有限的,返回ToString(value)
        b. 否则返回”null“
  11. 如果Type(value)是一个对象并且IsCallable(value) 为false
        a.使得 isArray=IsArray(value)
        b. ReturnIfAbrupt(isArray)
        c. 如果isArray为true返回SerializeJSONArray(value)
        d. 否则返回SerializeJSONObject(value)
12. 返回undefined
24.3.2.2 运行时语义:QuoteJSONString(value)
用引号来包裹String value并且转义一些特殊的字符
1. let product=""
2. 对于value中的每个字符C
   a. 如果c是引号或者反斜线,那么
         i. 使得product=product+'/'
        ii. 使得product=product+C
    b.否则,如果C是0x0008 (BACKSPACE), 0x000C (FORM FEED), 0x000A (LINE FEED), 0x000D (CARRIAGE RETURN), or 0x000B (LINE TABULATION)
         i. 使得product=product+'/'
        ii. 使得abbrev为相应的字符在C中的缩写
                BACKSPACE	"b"
                FORM FEED (FF)	"f"
                LINE FEED (LF)	"n"
                CARRIAGE RETURN (CR)	"r"
                LINE TABULATION	"t"
            iii.使得product=product+abbrev
  c. 否则如果C有space,那么
      i. 使得product=product+'\',那么
      ii.使得product=product+'u'
     iii. 使得hex=4个16位进制数字的字符串,字母16位进制数字是小写
      iV.使得product=product+hex
  d. 否则,
    i. 使得product=product+c
3.使得product=product+引号
4.return product
24.3.2.3 运行时语义:SerializeJSONObject(value)
SerializeJSONObject用来序列化一个object.它能访问stack,indent,gap,以及PropertyList values
1. 如果stack包含value,抛出一个TypeError因为结构是循环的
2. 把value接到stack中去
3. 使得stepback=indent
4. 使得indent=indent+gap
5. 如果PropertyList是undefined
     a. 使得k=PropertyList
6. 否则
     a. 使得k=EnumerableOwnNames(value)
7. 使得partial=一个空的list
8. 循环K中的元素P
     a. 使得strP=SerializeJSONProperty(P,value)
     b. ReturnIf Abrupt(strP)
     c. 如果strP不是undefined,那么,
           i. 使得member=QuoteJSONString(P)
          ii. 使得member=member+“:”
         iii. 如果gap不是空字符串
                      1. 使得member=member+code unit 0x0020(SPACE)
          iv. 使得member=member+strP
           v. 把member接在strP后面
9. 如果partial是空的,那么 
        a. 使得final="{ }"
10. 否则
        a. 如果gap是一个空字符串
               i. 使得properties=concat partial中所有的元素string,用逗号作为分隔符
              ii. 使得final=“{”+properties+“}”
         b. 否则 gap 不是一个空字符串
               i. 使得separator=逗号+line feed+indent
              ii. 使得properties=concat partial中所有的元素string,用逗号作为分隔符,分隔符不在第一个字符串的前面也不再最后一个字符串的后面
              iii. 使得final=“{”+line feed+indent+properties+code unit 0x000A,+stepback+"}"
11. 移除stack中的最后一个元素
12.使得indent=stepback
13. 返回final

23.3.2.4 运行时语义:SerializeJSONArray(value)
 这个方法可以访问stack,indent,还有gap
1.如果stack包含value抛出TypeError
2. 把value 接到stack中
3. 使得stepback=indent
4. 使得indent=concat indent and gap
5. 使得partial=空的list
6. 使得 len=ToLength(Get(value,"length"))
7. ReturnIfAbrupt(len)
8. 使得index=0
9.当index<len时
     a. 使得strP=SerializeJSONProperty(ToString(index),value)
     b.returnIfAbrupt(strP)
     c. 如果strP是undefined那么
           i.把"null" 接到partial
      d. 否则,
           i. 把strP接到partial
      e. index=index+1
10. 如果partial为空,那么,
       a. 使得final="[]"
11. 否则,
       a.如果gap是一个空字符串那么
             i. 使得properties=partial中的string元素以逗号连接起来。逗号不加在第一个string之前,也不加在最后一个string之后
            ii. 使得final="["+properties+"]"
       b. 否则
             i. 使得separator=逗号+line feed+indent
             ii.使得properties=partial中所有的String元素和相邻的seperator。seperator字符串不要在第一个字符串前面插入,也不要在最后一个字符串后面插入
             iii.使得final为“[”和line feed,indent,properties,code unit 0x000A,stepback和“]”组成
   12. 除去stack中的最后一个元素
   13.使得indent=stepback
   14. 返回final
Note:数组包含索引为0到array.length-1 的元素。属性不在数组的索引中的元素不在序列化的范围之列。数组被序列化成左方括号,被逗号分隔的元素,右方括号 

@MissNanLan
Copy link

首先我们看看它的作用

作用

JSON.stringify() 方法是将一个javascript的值(对象或者是数组)转化一个JSON字符串

格式

JSON.stringify(value[, replacer, [, space]]),value是必须的就不必说了;

  • 如果replacer是一个函数,则可以选择性的替换值;
    如果制定了replacer是一个数组,可选择性的仅包含数组指定的属性
  • space指定缩进用的空白字符串,用于美化输出

JSON.stringify() 将值转化为相应的JSON格式

  1. 基本数据类型
  • undefined
    JSON.stringify(undefined); // undefined

  • boolean
    JSON.stringify(ture); // 'true'

  • number,NaN 和Infinity都是null
    JSON.stringify(12); // '12' JSON.stringify(NaN); // 'null' JSON.stringify(Infinity); // 'null'

  • null
    JSON.stringify(null); // null

  • srtring
    JSON.stringify("11"); // " ''11'' "

  • symbol

    let sy = new symbol("111"); JSON.stringify(sy); // undefined
    2、function
    function JSONStringify(){} ; JSON.stringify(JSONStringify); // undefined
    3、 object

  • 如果是数组的话(数组里面有null和 undefined)

let arr3 = [null,undefined,1,2,3];
"[null,null,1,2,3]"
  •  如果对象是date的话,那么返回DatetoJSON 字符串值
    image.png
  • 如果对象是reg的话,那么返回 {}
    image.png
  • 如果是一般的对象的话
    image.png

@chongyangwang
Copy link

JSON.stringfy()的作用:将一个json对象转化为字符串。
JSON.stringfy(value,[replacer,space])的参数说明:
第一个参数不提,后面两个参数是可选参数 replacer 作为一个函数,作用是每一个要转化的属性值都要经过这个函数,若属性值为数组 则只有数组中出现的属性才可以被转化 如果该参数为null或为提供 则 转化所有属性值,可选参数第二个表示缩进的空格 ,没有该参数 ,则代表无缩进空格

使用JSON.stringfy传入不同参数
基本数据类型:
JSON.stringfy(undefined) // 返回undefined 类型undefined
JSON.stringfy(Number) // 若Number.isNaN()为true 则返回undefined 否则返回
toString(number)
JSON.stringfy(Boolean) // 返回true 类型string
JSON.stringfy(Symbol) // 返回 undefined
JSON.stringfy(string) // 返回string
JSON.stringfy(null) // 返回null 类型是string

函数类型
JSON.stringfy(function(){}) // undefined

对象类型
如果是普通对象 属性值不包含 undefined null 等 则调用toJSON方法
如果是正则对象 则返回 {}
如果是日期对象 返回该对象的toJSON方法
如果对象的属性值包含 undefined null symbol 等 则转为undefined
属性值数组 null

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants