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 相关文章推荐
Extjs4 GridPanel 的几种样式使用介绍
Apr 18 Javascript
jquery实现树形菜单完整代码
Dec 29 Javascript
HTML5+jQuery插件Quicksand实现超酷的星际争霸2兵种分类展示效果(附demo源码下载)
May 25 Javascript
浅谈JavaScript 执行环境、作用域及垃圾回收
May 31 Javascript
Javascript中this绑定的3种方法与比较
Oct 13 Javascript
JavaScript登录验证码的实现
Oct 27 Javascript
通过bootstrap全面学习less
Nov 09 Javascript
JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法
Apr 28 Javascript
vue2.0与bootstrap3实现列表分页效果
Nov 28 Javascript
Javascript实现购物车功能的详细代码
May 08 Javascript
Node.js使用Angular简单示例
May 11 Javascript
ES6小技巧之代替lodash
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的SQL注入实现(测试代码安全不错)
2011/02/27 PHP
使用php实现下载生成某链接快捷方式的解决方法
2013/05/07 PHP
PHP包含文件函数include、include_once、require、require_once区别总结
2014/04/05 PHP
详解WordPress开发中wp_title()函数的用法
2016/01/07 PHP
php json中文编码为null的解决办法
2016/12/14 PHP
使用prototype.js进行异步操作
2007/02/07 Javascript
[转]JS宝典学习笔记
2007/02/07 Javascript
jquery 列表双向选择器之改进版
2013/08/09 Javascript
浏览器页面区域大小的js获取方法
2013/09/21 Javascript
js动态往表格的td中添加图片并注册事件
2014/06/12 Javascript
深入理解JavaScript系列(39):设计模式之适配器模式详解
2015/03/04 Javascript
再谈JavaScript线程
2015/07/10 Javascript
Bootstrap每天必学之导航条(二)
2016/03/01 Javascript
js小数计算小数点后显示多位小数的实现方法
2016/05/30 Javascript
详解js的六大数据类型
2016/12/27 Javascript
Nodejs实现短信验证码功能
2017/02/09 NodeJs
vue.js国际化 vue-i18n插件的使用详解
2017/07/07 Javascript
vue2.0开发入门笔记之.vue文件的生成和使用
2017/09/19 Javascript
bootstrap-table.js扩展分页工具栏(增加跳转到xx页)功能
2017/12/28 Javascript
jQuery实现侧边栏隐藏与显示的方法详解
2018/12/22 jQuery
小程序hover-class点击态效果实现
2019/02/26 Javascript
windows下python安装paramiko模块和pycrypto模块(简单三步)
2017/07/06 Python
Django重装mysql后启动报错:No module named ‘MySQLdb’的解决方法
2018/04/22 Python
Python在for循环中更改list值的方法【推荐】
2018/08/17 Python
python学生信息管理系统(初级版)
2018/10/17 Python
Python实现基于SVM的分类器的方法
2019/07/19 Python
python模拟鼠标点击和键盘输入的操作
2019/08/04 Python
python常见字符串处理函数与用法汇总
2019/10/30 Python
paramiko使用tail实时获取服务器的日志输出详解
2020/12/06 Python
毕业实习个人鉴定范文
2013/12/10 职场文书
高速铁道技术专业求职信
2014/08/09 职场文书
2014年纪检监察工作总结
2014/11/11 职场文书
最美乡村教师观后感
2015/06/11 职场文书
银行柜员工作心得体会
2016/01/23 职场文书
springboot集成springCloud中gateway时启动报错的解决
2021/07/16 Java/Android
win10输入法不见了只能打出字母怎么解决?
2022/08/05 数码科技