本文介绍了新的ECMAScript 5函数存在什么现代化脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ECMAScript 5有很多好的补充。 。以下是一个很好的。



对于不支持这些功能的浏览器,很多这样的东西可以伪造。你知道任何脚本可以做到这一点吗?我对Object.create特别感兴趣。



例如,在创建JSON函数之前检查JSON函数是否存在。



如果还有更多像JSON一样,我们可以在需要使用新函数时添加它们。

解决方案

这种 Object.create shim:

  if(typeof Object.create!=function) {
Object.create = function(o){
function F(){}
F.prototype = o;
return new F;
};
}

但请不要这样做



此方法的问题是ES5 Object.create 2个参数的签名:first - 要继承的对象,second(可选) - 表示要添加到新创建对象的属性(或更确切地说,描述符)的对象。

  Object.create(O [,Properties]); // see 15.2.3.5,ECMA-262 5th ed。 

我们有一个不一致的实现,有两种不同的行为。在具有原生 Object.create 的环境中,方法知道如何处理第二个参数;在没有原生 Object.create 的环境中,它没有。



好吧,如果有一些代码(比如第三方脚本)想要使用 Object.create 为此代码:

  if(Object.create){
var child = Object.create ,属性);
}

- 基本上假设如果 Object.create 存在,它必须符合specs - accept第二个参数并向对象添加相应的属性。



但是,使用上述垫片,第二个参数会被忽略。甚至没有一个迹象表明不同。一个沉默的失败,可以这么说 - 这是非常痛苦的检测和修复。



我们能做得更好吗?



实际上不可能只使用(标准)创建一个完全符合 Object.create )ES3设施



但是,您可以尝试以下几种替代方法(不是最佳):



1)通知用户无法使用第二个参数

  if(!Object.create) {
Object.create = function(o){
if(arguments.length> 1){
throw Error('second argument is not supported');
}
// ...继续...
};
}

2)尝试处理第二个参数:

  if(!Object.create){
Object.create = function(parent,properties){
function F(){}
F.prototype = parent;
var obj = new F;
if(properties){
// ... augment obj ...
}
return obj;
};
}

请注意,属性是表示属性描述符,而不仅仅是属性名称/值,并且是不是很微不足道的支持(有些事情是不可能的,如控制属性的枚举):

  Object.create(parent,{
foo:{
value:'bar',
writable:true
},
baz:{
get:function(){return'baz getter';},
set:function(value){return'baz setter';},
enumerable:true
}
});

原始shim中的另一个不一致是它不会处理父对象 null

  var foo = Object.create (空值); 

这将创建一个对象,其[[Prototype]] null ;换句话说,不继承任何东西的对象,甚至不是 Object.prototype (ECMAScript中的所有本地对象都继承自)。

  foo.toString; // undefined 
foo.constructor; // undefined
//等

顺便说一下, 正确的ECMAScript中的散列表。



可以模拟这种行为,但只能使用非标准的扩展,例如magical __ proto__ 属性(因此实现将不是非常便携或鲁棒)。这个问题的解决方案是类似的:完全模仿ES5实现,或通知有关不一致/失败。


ECMAScript 5 has quite a few nice additions. John Resig has a good overview here. Here is a good ECMAScript 5 compatibility table.

A lot of this stuff can be "faked" for browsers that don't support these functions yet. Do you know of any scripts that can do this? I'm particularly interested in Object.create.

For example, Douglas Crockford's JSON script checks if JSON functions exist before creating them.

If there was more like the JSON one we could include them when we need to use the new functions.

解决方案

Crockford recommends this kind of Object.create shim:

if (typeof Object.create != "function") {
  Object.create = function (o) {
    function F(){}
    F.prototype = o;
    return new F;
  };
}

But please don't do this.

The problem with this approach is that ES5 Object.create has a signature of 2 arguments: first — an object to inherit from, and second (optional) — an object representing properties (or rather, descriptors) to add to newly created object.

Object.create(O[, Properties]); // see 15.2.3.5, ECMA-262 5th ed.

What we have is an inconsistent implementation with 2 different behaviors. In environments with native Object.create, method knows how to handle second argument; in environments without native Object.create, it doesn't.

What are the practical implications?

Well, if there's some code (say, a third party script) that wants to use Object.create, it's rather reasonable for that code to do this:

if (Object.create) {
  var child = Object.create(parent, properties);
}

— essentially assuming that if Object.create exists, it must conform to specs — accept second argument and add corresponding properties to an object.

But, with the above-mentioned shim, second argument is simply ignored. There's not even an indication of something going differently. A silent failure, so to speak — something that's rather painful to detect and fix.

Can we do better?

Well, it's actually impossible to create a fully-conforming Object.create shim using only (standard) ES3 facilities. The best solution is to create a custom wrapper method.

There are, however, few alternative (less than optimal) things you can try:

1) Notify user about inability to work with second argument

if (!Object.create) {
  Object.create = function (o) {
    if (arguments.length > 1) { 
      throw Error('second argument is not supported'); 
    }
    // ... proceed ...
  };
}

2) Try to handle second argument:

if (!Object.create) {
  Object.create = function (parent, properties) {
    function F(){}
    F.prototype = parent;
    var obj = new F;
    if (properties) {
      // ... augment obj ...
    }
    return obj;
  }; 
}

Note that "properties" is an object representing property descriptors, not just property names/values, and is something that's not very trivial to support (some things are not even possible, such as controlling enumerability of a property):

Object.create(parent, {
  foo: {
    value: 'bar',
    writable: true
  },
  baz: {
    get: function(){ return 'baz getter'; },
    set: function(value){ return 'baz setter'; },
    enumerable: true
  }
});

The other inconsistency in the original shim is that it doesn't take care of parent object being null.

var foo = Object.create(null);

This creates an object whose [[Prototype]] is null; in other words, object that doesn't inherit from anything, not even Object.prototype (which all native objects in ECMAScript inherit from).

foo.toString; // undefined
foo.constructor; // undefined
// etc.

This is, by the way, useful to create "proper" hash tables in ECMAScript.

It's possible to emulate this behavior, but only using non-standard extensions, such as "magical" __proto__ property (so implementation would be not very portable or robust). Solution to this problem is similar: either emulate ES5 implementation fully, or notify about inconsistency/failure.

这篇关于新的ECMAScript 5函数存在什么现代化脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-12 07:54