__proto__属性很特殊,它提供了Object.getPrototypeOf方法所不具备的额外能力,即修改对象原型链接的能力。

避免修改__proto__属性的最明显的原因是可移植性的问题。并不是所有的平台都支持修改对象原型的特性,所以无法编写可移植的代码。

避免修改__proto__属性的另一个原因是性能问题。所有现代的js引擎都深度优化了获取和设置对象属性的行为,因为这些都是一些常见的js操作。这些优化都是基于引擎对对象结构的认识上。当更改了对象的内部结构(如添加或删除该对象或其原型链中的对象的属性),将会使一些优化失效。修改__proto__属性实际上改变了继承结构本身,这可能是最具破坏性的修改。

避免修改__proto__属性的最大的原因是为了保持行为的可预测性。对象的原型链通过其一套确定的属性及属性值来定义它的行为。修改对象的原型链就像对其进行“大脑移植”,这会交换对象的整个层次结构。在某些情况下这样的操作可能是有用的,但是保持继承层次结构的相对稳定是一个基本的原则。

可以使用ES5中的Object.create函数来创建一个具有自定义原型链的新对象。对于不支持ES5的运行环境,可以使用兼容代码。

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

提示

  • 始终不要修改对象的__proto__属性

  • 使用Object.create函数给新对象设置自定义的原型

附录一:__proto__的语法

浏览器支持情况测试

使用方法

var shape = {};
var circle = new Circle();
in real code.
shape.__proto__ = circle;
console.log(shape.__proto__ === circle); // true
var shape = function () {};
var p = {
a: function () {
console.log('aaa');
}
};
shape.prototype.__proto__ = p; var circle = new shape(); circle.a();//aaa console.log(shape.prototype === circle.__proto__);//true //or var shape = function () {
};
var p = {
a: function () {
console.log('a');
}
}; var circle = new shape();
circle.__proto__ = p; circle.a(); // a console.log(shape.prototype === circle.__proto__);//false //or function test() {
}
test.prototype.myname = function () {
console.log('myname'); }
var a = new test() console.log(a.__proto__ === test.prototype);//true a.myname();//myname //or var fn = function () {
};
fn.prototype.myname = function () {
console.log('myname');
} var obj = {
__proto__: fn.prototype
}; obj.myname();//myname

[Effective JavaScript 笔记]第32条:始终不要修改__proto__属性的更多相关文章

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

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  2. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

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

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

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

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

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

    之前的43条,44条讨论了属性的枚举,但都没有彻底地解决属性查找中原型污染的问题.看下面关于字典的一些操作 'zhangsan' in dict; dict.zhangsan; dict.zhangs ...

  6. [Effective JavaScript 笔记]第20条:使用call方法自定义接收者来调用方法

    不好的实践 函数或方法的接收者(即绑定到特殊关键字this的值)是由调用者的语法决定的.方法调用语法将方法被查找的对象绑定到this变量,(可参阅之前文章<理解函数调用.方法调用及构造函数调用之 ...

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

    第43条中讲到的就算是用了Object的直接实例,也无法完全避免,Object.prototype对象修改,造成的原型污染.防止原型污染最简单的方式之一就是不使用原型.在ES5之前,并没有标准的方式创 ...

  8. [Effective JavaScript 笔记] 第9条:始终声明局部变量

    如果忘记将变量声明为局部变量,该变量将会隐式地转变为全局变量 function swap(a,i,j){ temp=a[i]; a[i]=a[j]; a[j]=temp; } 尽管该程序没有使用var ...

  9. [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑

    构建异步API的一种流行的替代方式是使用promise(有时也被称为deferred或future)模式.已经在本章讨论过的异步API使用回调函数作为参数. downloadAsync('file.t ...

随机推荐

  1. Android--手持PDA读取SD卡中文件

    近两年市场上很多Wince设备都开始转向Android操作系统,最近被迫使用Android开发PDA手持设备.主要功能是扫描登录,拣货,包装,发货几个功能.其中涉及到商品档的时候大概有700左右商品要 ...

  2. EasyUI——弹窗展示数据代码

    JS代码: $("#editDv").css("display","block"); $("#editDv").dial ...

  3. zabbix修改密码

    在我们刚刚安装好zabbix之后我们的管理用户是 Admin,密码是zabbix 所以我们肯定是要更改密码的,这个方法也适用于我们忘记管理员密码 首先我们登录mysql数据库 这里有一个zabbix库 ...

  4. Java 并发编程 Executor

    Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,Completion ...

  5. Java基础-重写-子类重写父类中的方法后执行情况

    代码 public class Test { public static void main(String[] args) { Shape shape = new Circle(); System.o ...

  6. 【CodeForces 620D】Professor GukiZ and Two Arrays

    题 题意 两个数列,一个有n个数,另一个有m个数,让你最多交换两次两个数列的数,使得两个数列和的差的绝对值最小,求这个差的绝对值.最少交换次数.交换数对 分析 交换0次.1次可得到的最小的差可以枚举出 ...

  7. Yii2修改默认布局

    public $layout = 'layout';//在类中定义一个变量,名为$layout的php文件 <?php echo $content; ?>

  8. TOMOYO Linux(undone)

    目录 . TOMOYO Introduction . TOMOYO Sourcecode Analysis 1. Introduction TOMOYO是一款基于LSM Framework实现的LSM ...

  9. SPOJ Pouring Water

    传送门 POUR1 - Pouring water #gcd #recursion Given two vessels, one of which can accommodate a litres o ...

  10. 优秀大数据GitHub项目一览

    http://blog.csdn.net/yaoxtao/article/details/50540485 优秀大数据GitHub项目一览 VMware CEO Pat Gelsinger曾说: 数据 ...