[Effective JavaScript 笔记]第31条:使用Object.getPrototypeOf函数而不要使用__proto__属性

ES5引入Object.getPrototypeOf函数作为获取对象原型的标准API,但由于之前的很多js引擎使用了一个特殊的__proto__属性来达到相同的目的。但有些浏览器并不支持这个__proto__属性,所以并不是完全兼容的。
例如对于拥有null原型的对象,不同的环境结果就不同了。

var empty=Object.create(null);
‘__proto__‘ in empty;//一些环境会返回false,另一些会返回true

这就导致结果的不一致,从而影响到依赖这个判断的相关代码。

无论在什么情况下,Object.getPrototypeOf函数都是有效的,而且它是提取对象原型更加标准、可移植的方法。由于__ptoto__属性会污染所有的对象,因此它会导致大量的bug。
对于一些没有提供该ES5 api的js环境,可以很容易利用__proto__属性来实现Object.getPrototypeOf函数。

if(typeof Object.getPrototypeOf === ‘undefined‘){
    Object.getPrototypeOf=function(obj){
         var t=typeof obj;
         if(!obj || (t !== ‘object‘ && t !== ‘function‘)){
            throw new Error("不是一个对象!");
         }
         return obj.__proto__;
    }
}

上面代码对宿主环境是否实现Object.getPrototypeOf函数进行判断,在ES5标准的环境中也很安全。

提示

  • 使用符合标准的Object.getPrototypeOf函数而不要使用非标准的__proto__属性
  • 在支持__proto__属性的非ES5环境中实现Object.getPrototypeOf函数
时间: 2024-11-06 03:11:00

[Effective JavaScript 笔记]第31条:使用Object.getPrototypeOf函数而不要使用__proto__属性的相关文章

[Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+1}" 反射获取函数源代码的功能很强大,使用函数对象的toString方法有严重的局限性.toString方法的局限性ECMAScript标准对函数对象的toString方法的返回结果(即该字符串)并没有任何要求.这意味着不同的js引擎将产生不同的字符串,甚至产生的字符串与该函数并不相关. 如果函数

[Effective JavaScript 笔记] 第14条:当心命名函数表达式笨拙的作用域

js函数会根据上下文改变其含义. function double(x){return x*2;} 这是一个函数声明,也可以是一个命名函数表达式(named function expression),取决于它出现的地方. 声明一个函数,并绑定一个当前作用域的变量. 同一段函数代码也可以作为一个表达式. var f=function double(x){return x*2;} 根据ECMAScript规范,该函数绑定到变量f,而不是变量double.这里给函数表达式命名并不是必要的的,可以直接使用

[Effective JavaScript 笔记]第29条:避免使用非标准的栈检查属性

许多js环境都提供检查调用栈的功能.调用栈是指当前正在执行的活动函数链.在某些旧的宿主环境中,每个arguments对象含有两个额外的属性:arguments.callee和arguments.caller.前者指向使用该arguments对象被调用的函数.后者指向调用该arguments对象被调用的函数的函数.许多环境支持arguments.callee,但它除了允许匿名函数递归地引用自身之外,没有更多的用途了.(高3中认为使用arguments.callee可以解除函数体内的代码和函数名之间

[Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //"number" typeof "s";//"string" typeof null;//"object":ECMAScript把null描述为独特的类型,但返回值却是对象类型,有点困惑. 可以使用Object.prototype.t

[Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式传递给eval函数以达到同样的功能.程序员面临一个选择:应该将代码表示为函数还是字符串?毫无疑问,应该将代码表示为函数.字符串表示代码不够灵活的一个重要原因是:它们不是闭包. 闭包回顾 看下面这个图 js的函数值包含了比调用它们时执行所需要的代码还要多的信息.而且js函数值还在内部存储它们可能会引用

Effective JavaScript Item 31 优先使用Object.getPrototypeOf,而不是__proto__

本系列作为Effective JavaScript的读书笔记. 在ES5中引入了Object.getPrototypeOf作为获取对象原型对象的标准API.可是在非常多运行环境中.也提供了一个特殊的__proto__属性来达到相同的目的. 由于并非全部的环境都提供了这个__proto__属性,且每一个环境的实现方式各不同样,因此一些结果可能不一致: // 在某些环境中 var empty = Object.create(null); // object with no prototype "__

[Effective JavaScript 笔记]第47条:绝不要在Object.prototype中增加可枚举的属性

之前的几条都不断地重复着for...in循环,它便利好用,但又容易被原型污染.for...in循环最常见的用法是枚举字典中的元素.这里就是从侧面提出不要在共享的Object.prototype中增加可枚举的属性.这就导致,我们在开发的时候,不能在Object.prototype中添加有用的方法.如,我们想增加一个产生对象属性名数组的allKeys方法将会怎么样? Object.prototype.allKeys=function(){ var res=[]; for(var key in thi

[Effective JavaScript 笔记]第45条:使用hasOwnProperty方法以避免原型污染

之前的43条,44条讨论了属性的枚举,但都没有彻底地解决属性查找中原型污染的问题.看下面关于字典的一些操作 'zhangsan' in dict; dict.zhangsan; dict.zhangsan=22; js的对象操作总是经继承的方式工作的.即使是一个空的对象字面量也是继承了Object.protoype属性. var dict={}; 'zhangsan' in dict;//false 'lisi' in dict;//false 'wangwu' in dict;//false'

[Effective JavaScript 笔记]第44条:使用null原型以防止原型污染

第43条中讲到的就算是用了Object的直接实例,也无法完全避免,Object.prototype对象修改,造成的原型污染.防止原型污染最简单的方式之一就是不使用原型.在ES5之前,并没有标准的方式创建一个空原型的新对象. 尝试 设置构造函数的原型属性为null或undefined function C(){} C.prototype=null; 结果 实例化该构造函数仍然得到是Object的实例. var c=new C(); Object.getPrototypeOf(c) === null