JavaScript prototype属性深入介绍


Posted in Javascript onNovember 27, 2012

每个函数创建时默认带有一个prototype属性,其中包含一个constructor属性,和一个指向Object对象的隐藏属性__proto__。constructor属性的值为该函数的对象。在一个函数前面加上new来调用,则会创建一个隐藏连接到该函数prototype成员的新对象(由__proto__属性来链接),同时函数的this将会被绑定到那个新对象上。
函数总是返回一个值;如果没有指定返回值,就返回undefined;如果当做构造函数来调用,且返回值不是对象,则返回this(该新对象);如果返回值是对象,则它作为构造函数是没有意义的!
[javascript]

function A(){ 
this.p = 'haha'; 
return {p:'heihei'}; 
} 
var a = new A(); 
function A(){ 
this.p = 'haha'; 
return {p:'heihei'}; 
} 
var a = new A(); 
alert(a.p);//显示'heihei',与var a = A();的效果一样

函数A内部直接调用一个函数B,B的this绑定到全局对象而不是其外部函数A,这是JS设计的一个错误。我们不得不用别的方式来解决这个问题,比如在A中用一个变量(通常是that)来保存A的this作用域的引用。
JS函数拥有一个length属性,表示函数定义时指定的形参的个数。
函数的arguments属性包含了调用函数时传入的所有参数,而不管函数的声明中是否定义了这些形参;arguments不是数组,只是一个“类似数组”的对象(在函数中运行arguments instanceof Array;返回false)。可以通过Array.prototype.slice.apply(arguments)将其转化为JS数组。
给JavaScript函数的原型增加方法(method),则所有的(构造)函数都可以用了!例如,可以给JS函数的构造者 Function 的原型增加一个method方法,则包括Object、Number等构造函数在内的所有函数都继承了该方法,这是很强大的:
[javascript]
Function.prototype.method = function(name, func){ 
this.prototype[name] = func; 
return this; 
}; 
Function.prototype.method = function(name, func){ 
this.prototype[name] = func; 
return this; 
};

这样,调用Object.method方法,就可以为所有的JS对象(包括Function对象)增加新的方法,调用Number.method方法,可以为所有的数值类型增加新的方法,下面一条就是这样的一个例子。 注意Object、Number等类型的对象此时并没有继承method方法。如果想达到这样的目的,可以运行类似下面的语句:
[javascript]
Object.method('method',Object.method); 
Object.method('method',Object.method);

我们可以通过修改数值类型的原型,来给数值类型增加新的方法,这里我们借用上一条中提到的method方法来给Number的原型增加一个negative方法:
[javascript]
Number.method(negative,function(){ 
return 0?this; 
}) 
Number.method(negative,function(){ 
return 0?this; 
})

调用方法的时候稍微有一点绕。在JavaScript的语法中,数字后面直接跟点号,然后跟方法调用的语法是错误的;也就是说,3.negative()这样写是不对的。要想调用数值类型的方法,需要在数字后面加n个空格(n>=1),或者使用小括号将数字括起来,将其强制转化为表达式,然后再调用方法,或者干脆定义一个数值变量,也可以直接调用方法。也就是说,下面的写法都是正确的:
[javascript]
(3).negative();
3 .negative();
var n = 3; n.negative();
3['negative']();
(3).negative();
3 .negative();
var n = 3; n.negative();
3['negative']();
当使用函数表达式方法定义函数时,function后面的函数名可以用来递归地调用自己,并且这个名字不会被覆盖!我们来看下面的例子,
[javascript]
function a(n){ 
if(n>1) 
return a(n-1)+1; 
else 
return 1; 
}; 
function a(n){ 
if(n>1) 
return a(n-1)+1; 
else 
return 1; 
};

上述代码定义了一个函数a,并且其内部递归对自身进行了调用;现在我们用一个新的引用aa指向函数a,然后将原来的a改变,比如变为一个整数1,然后调用函数aa,如下面代码所示:
[javascript]
var aa = a; 
a = 1; 
aa(3); 
var aa = a; 
a = 1; 
aa(3);

则控制台报错:TypeError: Property 'a' of object [object Window] is not a function;很显然,原来的递归函数已经被破坏了。关于这个问题,我们可以在函数a的内部,用arguments.callee.caller来代替a,或者用一个函数表达式来定义函数:
[javascript]
var b = function a(n){ 
if(n>1) 
return a(n-1)+1; 
else 
return 1; 
}; 
var bb = b; 
a = 3; 
bb(3); 
var b = function a(n){ 
if(n>1) 
return a(n-1)+1; 
else 
return 1; 
}; 
var bb = b; 
a = 3; 
bb(3);

此时,bb函数能正确返回我们想要的结果。
为了提高JavaScript函数的封装性,我们可以定义函数化的构造器,下面是一个例子:
[javascript] 
var funcCons = function(spec){ 
var that = {}; 
that.getName = function(){ 
return spec.name; 
}; 
that.says = function(){ 
return spec.saying || ''; 
}; 
return that; 
}; 
var myFunc = funcCons({name:'NearEast'}); 
var funcCons = function(spec){ 
var that = {}; 
that.getName = function(){ 
return spec.name; 
}; 
that.says = function(){ 
return spec.saying || ''; 
}; 
return that; 
}; 
var myFunc = funcCons({name:'NearEast'});

这样,我们可以在构造器中定义一些私有变量(如字典表)和函数,而不必把它们全部暴露在外面。
Javascript 相关文章推荐
Node.js中使用Log.io在浏览器中实时监控日志(等同tail -f命令)
Sep 17 Javascript
jQuery源码解读之hasClass()方法分析
Feb 20 Javascript
简单的jQuery banner图片轮播实例代码
Mar 04 Javascript
JS基于构造函数实现的菜单滑动显隐效果【测试可用】
Jun 21 Javascript
js输出数据精确到小数点后n位代码
Jul 02 Javascript
js利用正则表达式检验输入内容是否为网址
Jul 05 Javascript
动态生成的DOM不会触发onclick事件的原因及解决方法
Aug 06 Javascript
详解Vue方法与事件
Mar 09 Javascript
vue loadmore 组件滑动加载更多源码解析
Jul 19 Javascript
Vue之Watcher源码解析(1)
Jul 19 Javascript
vue中利用simplemde实现markdown编辑器(增加图片上传功能)
Apr 29 Javascript
详解vue项目中实现图片裁剪功能
Jun 07 Javascript
Knockoutjs的环境搭建教程
Nov 26 #Javascript
jquery ajax请求实例深入解析
Nov 26 #Javascript
jquery validate poshytip 自定义样式
Nov 26 #Javascript
一个可拖拽列宽表格实例演示
Nov 26 #Javascript
JS编程小常识很有用
Nov 26 #Javascript
javascript:history.go()和History.back()的区别及应用
Nov 25 #Javascript
js实现拖拽 闭包函数详细介绍
Nov 25 #Javascript
You might like
php中时间轴开发(刚刚、5分钟前、昨天10:23等)
2011/10/03 PHP
php中拷贝构造函数、赋值运算符重载
2012/07/25 PHP
PHP isset()与empty()的使用区别详解
2017/02/10 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
2018/02/07 PHP
javascript编程起步(第四课)
2007/01/10 Javascript
获取焦点时,利用js定时器设定时间执行动作
2010/04/02 Javascript
jQuery EasyUI API 中文文档 可调整尺寸
2011/09/29 Javascript
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
2011/10/29 Javascript
JS中处理与当前时间间隔的函数代码
2012/05/23 Javascript
推荐25个超炫的jQuery网格插件
2014/11/28 Javascript
JavaScript正则获取地址栏中参数的方法
2017/03/02 Javascript
微信小程序实现拖拽 image 触摸事件监听的实例
2017/08/17 Javascript
Vue 设置axios请求格式为form-data的操作步骤
2019/10/29 Javascript
JS内置对象和Math对象知识点详解
2020/04/03 Javascript
Vue自定义表单内容检查rules实例
2020/10/30 Javascript
[02:17]TI4西雅图DOTA2前线报道 啸天mik夫妻档解说
2014/07/08 DOTA
Python使用PyGreSQL操作PostgreSQL数据库教程
2014/07/30 Python
Python进阶篇之字典操作总结
2016/11/16 Python
Python探索之爬取电商售卖信息代码示例
2017/10/27 Python
python and or用法详解
2019/06/26 Python
在python中实现同行输入/接收多个数据的示例
2019/07/20 Python
python每天定时运行某程序代码
2019/08/16 Python
python 内置函数汇总详解
2019/09/16 Python
Python通过VGG16模型实现图像风格转换操作详解
2020/01/16 Python
解决python父线程关闭后子线程不关闭问题
2020/04/25 Python
matplotlib.pyplot.matshow 矩阵可视化实例
2020/06/16 Python
HTML5 canvas基本绘图之绘制矩形
2016/06/27 HTML / CSS
Feelunique澳大利亚:欧洲的化妆品零售电商
2019/12/18 全球购物
毕业生简单求职信
2013/11/19 职场文书
财务经理的岗位职责
2013/12/17 职场文书
科研先进个人典型材料
2014/01/31 职场文书
应聘医药销售自荐书范文
2014/02/08 职场文书
出纳员岗位职责风险
2014/03/06 职场文书
改革共识倡议书
2014/08/29 职场文书
治庸问责心得体会
2014/09/12 职场文书
病假条格式范文
2015/08/17 职场文书