JavaScript中几个重要的属性(this、constructor、prototype)介绍


Posted in Javascript onMay 19, 2013

this
this表示当前对象,如果在全局作用范围内使用this,则指代当前页面对象window; 如果在函数中使用this,则this指代什么是根据运行时此函数在什么对象上被调用。 我们还可以使用apply和call两个全局方法来改变函数中this的具体指向。
先看一个在全局作用范围内使用this的例子:

<script type=> 
console.log( === window); 
console.log(window.alert === .alert); 
console.log(.parseInt(, 10)); 
</script>

函数中的this是在运行时决定的,而不是函数定义时,如下:
foo() { 
console.log(.fruit); 
} 
fruit = ; 
foo(); 
pack = { 
fruit: , 
foo: foo 
}; 
pack.foo();

全局函数apply和call可以用来改变函数中this的指向,如下:
foo() { 
console.log(.fruit); 
} 
fruit = ; 
pack = { 
fruit: 
}; 
foo.apply(window); 
foo.apply(pack);

注:apply和call两个函数的作用相同,唯一的区别是两个函数的参数定义不同
因为在JavaScript中函数也是对象,所以我们可以看到如下有趣的例子:
foo() { 
( === window) { 
console.log(); 
} 
} 
foo.boo = () { 
( === foo) { 
console.log(); 
} ( === window) { 
console.log(); 
} 
}; 
foo(); 
foo.boo(); 
foo.boo.apply(window);

prototype
prototype本质上还是一个JavaScript对象。 并且每个函数都有一个默认的prototype属性。
如果这个函数被用在创建自定义对象的场景中,我们称这个函数为构造函数。 比如下面一个简单的场景:
Person(name) { 
.name = name; 
} 
Person.prototype = { 
getName: () { 
.name; 
} 
} 
zhang = Person(); 
console.log(zhang.getName());

作为类比,我们考虑下JavaScript中的数据类型 - 字符串(String)、数字(Number)、数组(Array)、对象(Object)、日期(Date)等。 我们有理由相信,在JavaScript内部这些类型都是作为构造函数来实现的,比如:
Array() {
}
arr1 = Array(1, 56, 34, 12);
arr2 = [1, 56, 34, 12];
同时对数组操作的很多方法(比如concat、join、push)应该也是在prototype属性中定义的。
实际上,JavaScript所有的固有数据类型都具有只读的prototype属性(这是可以理解的:因为如果修改了这些类型的prototype属性,则哪些预定义的方法就消失了), 但是我们可以向其中添加自己的扩展方法。
Array.prototype.min = () {
min = [0];
( i = 1; i < .length; i++) {
([i] < min) {
min = [i];
}
}
min;
};
console.log([1, 56, 34, 12].min());
注意:这里有一个陷阱,向Array的原型中添加扩展方法后,当使用for-in循环数组时,这个扩展方法也会被循环出来。
下面的代码说明这一点(假设已经向Array的原型中扩展了min方法):
arr = [1, 56, 34, 12];
total = 0;
( i arr) {
total += parseInt(arr[i], 10);
}
console.log(total);
解决方法也很简单:
arr = [1, 56, 34, 12];
total = 0;
( i arr) {
(arr.hasOwnProperty(i)) {
total += parseInt(arr[i], 10);
}
}
console.log(total);
constructor
constructor始终指向创建当前对象的构造函数。比如下面例子:
arr = [1, 56, 34, 12]; 
console.log(arr.constructor === Array); 
Foo = () { }; 
console.log(Foo.constructor === Function); 
obj = Foo(); 
console.log(obj.constructor === Foo); 
console.log(obj.constructor.constructor === Function);

但是当constructor遇到prototype时,有趣的事情就发生了。
我们知道每个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数。如下例所示:
Person(name) { 
.name = name; 
}; 
Person.prototype.getName = () { 
.name; 
}; 
p = Person(); 
console.log(p.constructor === Person); 
console.log(Person.prototype.constructor === Person); 
console.log(p.constructor.prototype.constructor === Person);

当时当我们重新定义函数的prototype时(注意:和上例的区别,这里不是修改而是覆盖), constructor的行为就有点奇怪了,如下示例:
Person(name) { 
.name = name; 
}; 
Person.prototype = { 
getName: () { 
.name; 
} 
}; 
p = Person(); 
console.log(p.constructor === Person); 
console.log(Person.prototype.constructor === Person); 
console.log(p.constructor.prototype.constructor === Person);

为什么呢?
原来是因为覆盖Person.prototype时,等价于进行如下代码操作:
Person.prototype = Object({ 
getName: () { 
.name; 
} 
});

而constructor始终指向创建自身的构造函数,所以此时Person.prototype.constructor === Object,即是:
Person(name) { 
.name = name; 
}; 
Person.prototype = { 
getName: () { 
.name; 
} 
}; 
p = Person(); 
console.log(p.constructor === Object); 
console.log(Person.prototype.constructor === Object); 
console.log(p.constructor.prototype.constructor === Object);

怎么修正这种问题呢?方法也很简单,重新覆盖Person.prototype.constructor即可:
Person(name) { 
.name = name; 
}; 
Person.prototype = Object({ 
getName: () { 
.name; 
} 
}); 
Person.prototype.constructor = Person; 
p = Person(); 
console.log(p.constructor === Person); 
console.log(Person.prototype.constructor === Person); 
console.log(p.constructor.prototype.constructor === Person);
Javascript 相关文章推荐
javascript编程起步(第一课)
Jan 10 Javascript
用JS操作FRAME中的IFRAME及其内容的实现代码
Jul 26 Javascript
页面只有一个text的时候,回车自动submit的解决方法
Aug 12 Javascript
模拟select的代码
Oct 19 Javascript
对frameset、frame、iframe的js操作示例代码
Aug 16 Javascript
JavaScript 实现鼠标拖动元素实例代码
Feb 24 Javascript
基于bootstrap页面渲染的问题解决方法
Aug 09 Javascript
微信小程序Flex布局用法深入浅出分析
Apr 25 Javascript
jQuery zTree插件使用简单教程
Aug 16 jQuery
微信小程序官方动态自定义底部tabBar的例子
Sep 04 Javascript
Vue组件模板及组件互相引用代码实例
Mar 11 Javascript
vue 实现一个简单的全局调用弹窗案例
Sep 10 Javascript
js函数中onmousedown和onclick的区别和联系探讨
May 19 #Javascript
下拉菜单点击实现连接跳转功能的js代码
May 19 #Javascript
js操纵跨frame的三级联动select下拉选项实例介绍
May 19 #Javascript
固定背景实现的背景滚动特效示例分享
May 19 #Javascript
Jquery实现鼠标移上弹出提示框、移出消失思路及代码
May 19 #Javascript
扩展js对象数组的OrderByAsc和OrderByDesc方法实现思路
May 17 #Javascript
js获取元素到文档区域document的(横向、纵向)坐标的两种方法
May 17 #Javascript
You might like
关于Intype一些小问题的解决办法
2008/03/28 PHP
轻松修复Discuz!数据库
2008/05/03 PHP
php中计算程序运行时间的类代码
2012/11/03 PHP
hadoop常见错误以及处理方法详解
2013/06/19 PHP
PHP中array_slice函数用法实例详解
2014/11/25 PHP
php定义参数数量可变的函数用法实例
2015/03/16 PHP
thinkPHP导出csv文件及用表格输出excel的方法
2015/12/30 PHP
tp5框架使用cookie加密算法实现登录功能示例
2020/02/10 PHP
网页里控制图片大小的相关代码
2006/06/25 Javascript
IE与FireFox的兼容性问题分析
2007/04/22 Javascript
MooTools 1.2中的Drag.Move来实现拖放
2009/09/15 Javascript
最短的javascript:地址栏载入脚本代码
2011/10/13 Javascript
jquery的ajax()函数传值中文乱码解决方法介绍
2012/11/08 Javascript
js 上下左右键控制焦点(示例代码)
2013/12/14 Javascript
jQuery Easyui使用(二)之可折叠面板动态加载无效果的解决方法
2016/08/17 Javascript
Vue.js实现表格动态增加删除的方法(附源码下载)
2017/01/20 Javascript
nodejs结合socket.io实现websocket通信功能的方法
2018/01/12 NodeJs
vue+element的表格实现批量删除功能示例代码
2018/08/17 Javascript
解决layui checkbox 提交多个值的问题
2019/09/02 Javascript
[45:10]NB vs Liquid Supermajor小组赛 A组胜者组决赛 BO3 第二场 6.2
2018/06/04 DOTA
python中__call__内置函数用法实例
2015/06/04 Python
使用python画社交网络图实例代码
2019/07/10 Python
python 求定积分和不定积分示例
2019/11/20 Python
Python使用Chrome插件实现爬虫过程图解
2020/06/09 Python
完美解决keras保存好的model不能成功加载问题
2020/06/11 Python
浅析Python 责任链设计模式
2020/09/11 Python
Python获取android设备cpu和内存占用情况
2020/11/15 Python
加拿大鞋子连锁店:Town Shoes
2016/09/26 全球购物
js正则匹配markdown里的图片标签的实现
2021/03/24 Javascript
大四自我鉴定范文
2013/10/06 职场文书
对公司合理化的建议书
2014/03/12 职场文书
《诚实与信任》教学反思
2014/04/10 职场文书
教师纪念9.18事件演讲稿范文
2014/09/14 职场文书
支教个人总结
2015/03/04 职场文书
销售区域经理岗位职责
2015/04/10 职场文书
加强党性修养心得体会
2016/01/21 职场文书