__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. Angular JS 学习笔记(自定义服务:factory,Promise 模式异步请求查询:$http,过滤器用法filter,指令:directive)

    刚学没多久,作了一个小项目APP,微信企业号开发与微信服务号的开发,使用的是AngularJS开发,目前项目1.0版本已经完结,但是项目纯粹为了赶工,并没有发挥AngularJS的最大作用,这几天项目 ...

  2. OSX 上安装 Scrapy 的那些坑

    Scrapy 这个爬网框架真心不错,但在OSX上安装总是会出现各种的问题,在这里就作一个收集汇总.我的系统环境是 OS X El Capitan (10.11.1) 首先要保证 pip , virtu ...

  3. Jsp语法、指令及动作元素

    一.JSP的语法 1.JSP的模板元素:(先写HTML) 就是JSP中的那些HTML标记 作用:页面布局和美化 2.JSP的Java脚本表达式: 作用:输出数据到页面上 语法:<%=表达式%&g ...

  4. 20步打造最安全的NGINX WEB服务器

    Nginx 是一个轻量级的,高性能的Web服务器以及反向代理和邮箱(IMAP/POP3)代理服务器.它运行在UNIX,GNU /linux,BSD 各种版本,Mac OS X,Solaris和Wind ...

  5. eclipse中安装svn插件

    Eclipse安装SVN 1.help->Install New Software2.Work With,点击add      name:subclipse      url:http://su ...

  6. href="javascript:void(0)"

    javascript:是伪协议,表示url的内容通过javascript执行.void(0)表示不作任何操作,这样会防止链接跳转到其他页面.这么做往往是为了保留链接的样式,但不让链接执行实际操作,具体 ...

  7. [NOIP2008] 提高组 洛谷P1155 双栈排序

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  8. HDU1907 John

    Description Little John is playing very funny game with his younger brother. There is one big box fi ...

  9. Penetration Testing、Security Testing、Automation Testing

    相关学习资料 http://www.cnblogs.com/LittleHann/p/3823513.html http://www.cnblogs.com/LittleHann/p/3828927. ...

  10. spring 注解简单使用

    一.通用注解 1.项目结构: 2.新建Person类,注解@Component未指明id,则后期使用spring获取实例对象时使用默认id="person"方式获取或使用类方式获取 ...