[Effective JavaScript 笔记]第32条:始终不要修改__proto__属性
__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__属性的更多相关文章
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记]第45条:使用hasOwnProperty方法以避免原型污染
之前的43条,44条讨论了属性的枚举,但都没有彻底地解决属性查找中原型污染的问题.看下面关于字典的一些操作 'zhangsan' in dict; dict.zhangsan; dict.zhangs ...
- [Effective JavaScript 笔记]第20条:使用call方法自定义接收者来调用方法
不好的实践 函数或方法的接收者(即绑定到特殊关键字this的值)是由调用者的语法决定的.方法调用语法将方法被查找的对象绑定到this变量,(可参阅之前文章<理解函数调用.方法调用及构造函数调用之 ...
- [Effective JavaScript 笔记]第44条:使用null原型以防止原型污染
第43条中讲到的就算是用了Object的直接实例,也无法完全避免,Object.prototype对象修改,造成的原型污染.防止原型污染最简单的方式之一就是不使用原型.在ES5之前,并没有标准的方式创 ...
- [Effective JavaScript 笔记] 第9条:始终声明局部变量
如果忘记将变量声明为局部变量,该变量将会隐式地转变为全局变量 function swap(a,i,j){ temp=a[i]; a[i]=a[j]; a[j]=temp; } 尽管该程序没有使用var ...
- [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑
构建异步API的一种流行的替代方式是使用promise(有时也被称为deferred或future)模式.已经在本章讨论过的异步API使用回调函数作为参数. downloadAsync('file.t ...
随机推荐
- 【APUE】Chapter17 Advanced IPC & sign extension & 结构体内存对齐
17.1 Introduction 这一章主要讲了UNIX Domain Sockets这样的进程间通讯方式,并列举了具体的几个例子. 17.2 UNIX Domain Sockets 这是一种特殊s ...
- WDCP安装并配置php5.4和mongodb
记录一下,免得忘了.全部都是自己测试用过的安装过程没有问题. linux常用命令 mv 移动文件 mkdir 创建文件夹 rm 删除 cp 复制 netstat 网络状态 tar 解压 wget 下载 ...
- 学习之路三十二:VS调试的简单技巧
这段时间园子里讲了一些关于VS的快捷键以及一些配置技巧,挺好的,大家一起学习,一起进步. 这段时间重点看了一下关于VS调试技巧方面的书,在此记录一下学习的内容吧,主要还是一些比较浅显的知识. 1. 调 ...
- Bootstrap3.0学习第十六轮(进度条、媒体对象、列表组、面板)
详情请查看http://aehyok.com/Blog/Detail/23.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...
- AngularJs-MVC之路由、模块以及依赖注入
前面呢,我们大概的了解了下AngularJs的入门,也做过了hello world的一个demo,不知道大家有没有掌握呢?在下面我们需要讲一些AngularJS的一些干货. 1,一个完整项目的目录结构 ...
- tableviewCell的xib中collectionView签协议
- Linux下搭建nginx php环境
下载安装所需包 openssl-1.0.1i.tar.gz zlib-1.2.8.tar.gz pcre-8.35.tar.gz nginx-1.7.4.tar.gz 以上为nginx依赖文件 lib ...
- “耐撕”团队 2016.04.05 站立会议
1. 时间: 20:10--20:25 共计15分钟. 2. 成员: Z 郑蕊 * 组长 (博客:http://www.cnblogs.com/zhengrui0452/), P 濮成林(博客:ht ...
- attempted to assign id from null one-to-one
one-to-one在hibernate中可以用来作为两张表之间的主键关联,这也是hibernate中主键关联的一种用法,这样在一张表中的ID,在生成另外一张表的同时回自动插入到相应的ID字段中去,相 ...
- ASP.NET Web API实现POST报文的构造与推送
毕设和OAuth协议相关,而要理解OAuth协议就必须理解HTTP GET/POST方法.因此研究了一下如何使用Web API或MVC构造POST报文并实现客户端与服务器端的交互. 我使用的工具是Vi ...