js prototype之诡异
想必经常写js的人必然会经常性的用到prototype这个属性,我写这篇文章倒不是自己对prototype这个属性理解有多深刻,相反是因为自己理解肤浅,想通过写文章来加深理解。废话不多说。下面总结一下prototype的特征吧,也请高手砖头拍轻点。
- 特征一:“对象”是不可访问prototype属性,只有“类型”才可以访问portotype属性。
var x=0;
var y='1';
var z=[];
var w={};
var u=function(){}
// 以上对象类型中,仅有u是有protottype属性的,方法可以被看做是一种类型。
Array
Object
Function
Number
String
//以上是js的内置对象,它们是“类型”,都含有prototype属性
可以简单这么理解,可以通过new关键字的对象都包含prototype属性。
- 特征二:prototype是保存实例方法的真正所在。
valueof()、toString()、Array.push,call,apply等方法实际上都是保存在prototype属性的名下,只是我们实际使用这些方法时通过各自的实例来进行访问的。这样我们就可以通过prototype来重写这些方法了。
- 重写方法
Number.prototype.toString = function () {
return "Number:" + this;
}
var x= 222;
alert(x.toString());上边显示的结果是:"Number:222";
Function.prototype.toString = function () {
return "function { native code }";
}
function aaa() {
return Math.max(1, 2);
}
alert(aaa.toString());//给当前的脚本库进行简单的加密处理
- 扩充方法
Array.prototype.max = function () {
for (var i = 0, max = this[0]; this[i]; i++) {
if (max < this[i])
max = this[i];
}
return max;
}
// 此方法仅限正数比较,字符串或其他对象无法比较
- 特征三:prototype属性是特定类型对象的实例所共有的,也就是共享的一片内存区域,这片内存区域是在当前特定类型声明时创建的(如果特定类型是自定义函数,那么这片共享的内存区域就是在这个自定义函数声明时就开始创建)。对于特定类型的对象的prototype属性,他们在内存有且只保存着一份,只要你对prototype属性的修改,都会影响到所有的实例对象。
- prototype的属性让js实现了晚绑定和极晚绑定
请看下面的代码:
var x={};
var y={};
console.log(x===y);
// 这里是false,相信大家都知道为什么,因为它们在内存中所处的地址不一样
var x={};
var y=x;
console.log(x===y);
// 这里是true。
function Nothing() { }
Nothing.prototype.noArray = [];
Nothing.prototype.noObject = {};
var nothing1 = new Nothing();
var nothing2 = new Nothing();
console.log(nothing1.noArray === nothing2.noArray);
console.log(nothing1.noObject === nothing2.noObject);
// 此处,两个都为true,为什么呢,nothing1和nothing2公用了一片内存区域,它们都是指向空这个唯一的空对象和空数组的。
再举一个例证来说明:
function M() { }
M.prototype.val = 0;
var m1 = new M();
var m2 = new M();
console.log(m1.val);
console.log(m2.val);
// 这里会发现,两个值都是0
M.prototype.val = 2;
console.log(m1.val);
console.log(m2.val);
// 这里会发现,另个值都是2
- 特征四:当我们尝试通过“对象.属性=value”来修改prototype中的属性时,其实并没有修改portotype属性,而是给当前创建了一同名的属性,prototype中的属性还是保留着。
还是拿上边的代码继续进行分析:
function Nothing() { }
Nothing.prototype.noArray = [];
Nothing.prototype.noObject = {};
var nothing1 = new Nothing();
var nothing2 = new Nothing();
nothing1.noArray = null;
console.log(nothing1.noArray === nothing2.noArray);
console.log(nothing1.noObject === nothing2.noObject);
// 这个时候发现,第一个是false,第二个是true
我们看一下调试器发现,


我们发现nothing1对象多了一个普通的属性。也就是说,当你尝试对prototype中的属性进行修改的时候,你其实并没有修改prototype中的属性,而是新追加了一个同名的“普通”属性。
仔细分析上述代码,就会得出下面这条结论了。
- 特征五:当访问一个对象的某个属性的时候,优先访问的是“普通”属性,其次再访问prototype中的属性。
这样就能解释上面代码中第一个为什么是false了。同样,当删除对象属性时,优先删除的仍然是这个“普通属性”。
function Nothing() {}
Nothing.prototype.noArray = [];
Nothing.prototype.noObject = {};
var nothing1 = new Nothing();
var nothing2 = new Nothing();
nothing1.noArray = null;
console.log(nothing1.noArray === nothing2.noArray);
console.log(nothing1.noObject === nothing2.noObject);
// 第一个结果是false,第二个结果是true
delete nothing1.noArray;
console.log(nothing1.noArray === nothing2.noArray);
// 这时候nothing1.noArray是[],结果为true;
delete Nothing.prototype.noArray;
console.log(nothing1.noArray === nothing2.noArray);
// 这时候nothing1.noArray 和nothing2.noArray都为undefined,结果为true
js prototype之诡异的更多相关文章
- 深入理解js——prototype原型
之前(深入理解js--一切皆是对象)中说道,函数也是一种对象.它也是属性的集合,你也可以对函数进行自定义属性.而JavaScript默认的给了函数一个属性--prototype(原型).每个函数都有一 ...
- js prototype
1 原型法设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个类B,这个类是以A为原型的,并且能进行扩展.我们称B的原型为A. 2 javasc ...
- js prototype新感悟
prototype是js的一个原型属性,这个属性可以创建对象属性和方法. 子类继承原型属性时,会继承父类的原型属性和方法. prototype只能作用到类上,不能作用到对象上. ----------- ...
- [转] js prototype详解
JavaScript能够实现的面向对象的特征有:·公有属性(public field)·公有方法(public Method)·私有属性(private field)·私有方法(private fie ...
- js prototype __proto__ instanceof constructor
JS中有两个特殊的对象:Object与Function,它们都是构造函数,用于生成对象. Object.prototype是所有对象的祖先,Function.prototype是所有函数的原型,包括构 ...
- flexible.js字体大小诡异现象解析及解决方案
最近在做一个手机端页面时,遇到了一个奇怪的问题:字体的显示大小,与在CSS中指定的大小不一致.大家可以查看这个Demo(记得打开Chrome DevTools). 就如上图所示,你可以发现,原本指定的 ...
- (转)js prototype 详解
转载自:http://blog.csdn.net/chaojie2009/article/details/6719353(也是转载的.鄙视一下此人转载不著名出处.) 注意:必须带着怀疑的态度去看这篇文 ...
- JS prototype chaining(原型链)整理中······
初学原型链整理 构造器(constructor).原型(prototype).实例(instance); 每一个构造器都有一个prototype对象,这个prototype对象有一个指针指向该构造器: ...
- js——prototype、__proto__、constructor
Object 1. Object是一个函数(typeof O ...
随机推荐
- windows下配置lamp环境(2)---配置Apache服务器2.2.25
配置Apache 配置Apache时,先要找到安装目录中的主配置文httpd.conf,使用文本编辑器打开,最好不要使用windows自带的编辑器,可以使用NotePad++, vim,或者subli ...
- javascript闭包作用
闭包的简单概念:闭包就是能够读取其他函数内部变量的函数. 函数内部的函数闭包的两个最大的作用读取函数内部的变量变量的值始终保持在内存中function A(){ var n=999; nAdd=fun ...
- python学习第九天 -- 列表生产式
说说python特有的列表生成式.python的列表的生成式主要用法是什么? 用法就是可以使用简洁的代码生成出list集合. 直接用代码举了例子: 利用列表生成式生成列表[1x2,3x4,5x6,7x ...
- UCOS 信号量
uCOS-II信号量OSSemCreate(0)和OSSemCreate(1)详解 (2014-04-22 18:04:18) 转载▼ 标签: it 分类: 操作系统 在ucos-II中,为了实现任务 ...
- cf C. Find Maximum
http://codeforces.com/contest/353/problem/C 先预处理前i个数的和,然后找到第一个出现的1,然后变成0后的和与目前的和比较,如果大就更新. #include ...
- PCB正片和负片有什么区别
概念:正片和负片是底片的两种不同类型. 正片:简单地说就是,在底片上看到什么就有什么. 负片:正好相反,看到的就是没有的,看不到的就是有的.见下图: 在 Allegro中使用正负片的特点: 正片:优点 ...
- 利用Qt将网页保存为PDF
灵社区文章链接http://www.ituring.com.cn/article/128717起因是在群里和大家讨论自己做一个图灵社区的客户端,说没有API不好搞,后来fairjm童鞋发了个java版 ...
- CentOS6.5切换 语言(附带6.5官方下载地址)
1 在终端中输入命令[sudo vim /etc/sysconfig/i18n]来编辑i18n文件, 2 把“zh_CN.UTF-8”修改为“en_US.UTF-8”, 3 保存修改并退出,如果提示这 ...
- 再论dynamic 关键字
有关动态数据类型 ,大家估计在实际中用的比较多了,不是很陌生.有关自己在项目中 的实际钉子总结: 1 匿名对象中的字段,是只读的,不能赋值 2 动态类型 指向强类型实例,注意观察内部的属性可访问性 ...
- 2015必须要看的APP源码
多媒体类型 哔哩哔哩(bilibili)客户端源码 一个高仿哔哩哔哩(bilibili)客户端的开源项目,效果不错 下载地址: http://www.apkbus.com/forum.php?mod= ...