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

第 10 期(2019-05-17):JSON.parse方法polyfill #12

Open
wingmeng opened this issue May 17, 2019 · 3 comments
Open

第 10 期(2019-05-17):JSON.parse方法polyfill #12

wingmeng opened this issue May 17, 2019 · 3 comments

Comments

@wingmeng
Copy link
Collaborator

wingmeng commented May 17, 2019

类型:常用技巧
难度:★

JSON.parse() 方法写一个 polyfill,使其可以兼容低版本浏览器(IE8)

JSON.parse() 相关资料


参考答案:

!(window.JSON && window.JSON.parse) && !function(win) {
  win.JSON = {
    parse: function(str) {
      return new Function('return ' + str)()
    }
  }
}(window);

本期优秀回答者: @AMY-Y

@AMY-Y
Copy link

AMY-Y commented May 17, 2019

if (!window.JSON) {
  window.JSON = {
    parse: function(sJSON) { return eval('(' + sJSON + ')'); },
    stringify: (function () {
      var toString = Object.prototype.toString;
      var isArray = Array.isArray || function (a) { return toString.call(a) === '[object Array]'; };
      var escMap = {'"': '\\"', '\\': '\\\\', '\b': '\\b', '\f': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t'};
      var escFunc = function (m) { return escMap[m] || '\\u' + (m.charCodeAt(0) + 0x10000).toString(16).substr(1); };
      var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
      return function stringify(value) {
        if (value == null) {
          return 'null';
        } else if (typeof value === 'number') {
          return isFinite(value) ? value.toString() : 'null';
        } else if (typeof value === 'boolean') {
          return value.toString();
        } else if (typeof value === 'object') {
          if (typeof value.toJSON === 'function') {
            return stringify(value.toJSON());
          } else if (isArray(value)) {
            var res = '[';
            for (var i = 0; i < value.length; i++)
              res += (i ? ', ' : '') + stringify(value[i]);
            return res + ']';
          } else if (toString.call(value) === '[object Object]') {
            var tmp = [];
            for (var k in value) {
              if (value.hasOwnProperty(k))
                tmp.push(stringify(k) + ': ' + stringify(value[k]));
            }
            return '{' + tmp.join(', ') + '}';
          }
        }
        return '"' + value.toString().replace(escRE, escFunc) + '"';
      };
    })()
  };
}

虽然这是一道送分题,作为一直小白还是有点小疑惑请教

//对于
 eval('(' + sJSON + ')');
//在浏览器控制台里
var json={"a":"b","c":"d"}
eval(json);
{a: "b", c: "d"}//正常
var json={"a":"b","c":"d"}
eval("("+json+")");//报错
VM191:1 Uncaught SyntaxError: Unexpected identifier
    at <anonymous>:2:14
(anonymous) @ VM190:2
var json={"a":"b","c":"d"}
eval('('+json+')');//报错
VM205:1 Uncaught SyntaxError: Unexpected identifier
    at <anonymous>:2:14
(anonymous) @ VM204:2

这是为毛啊?

@wingmeng
Copy link
Collaborator Author

@AMY-Y 这题以及上述参考答案我是在 codewars 上看到的,我作答时用的也是 eval。new Function 这种方式非常巧妙的利用了 js 中的函数构造器,无论在性能、安全性还是代码健壮性上,都要比 eval 方式好得多。
你说的那两个报错的问题,是因为给 eval 的传参不对,它接收的应该是字符串,不能是一个对象,所以按 var json='{"a":"b","c":"d"}' 或者 var json="{a:\"b\",c:\"d\"}" 这样写就没问题,eval('('+json+')') 就能将其正确解析为对象了。
相关资料:https://www.jianshu.com/p/5d6523017981

@AMY-Y
Copy link

AMY-Y commented May 18, 2019

这下通了,之前困扰了我很久,感谢大神

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

2 participants