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 相关文章推荐
采用CSS和JS,刚好我最近有个站点要用到下拉菜单!
Jun 26 Javascript
JSON 客户端和服务器端的格式转换
Aug 27 Javascript
读jQuery之七 判断点击了鼠标哪个键的代码
Jun 21 Javascript
浅析Node.js查找字符串功能
Sep 03 Javascript
jQuery实现按钮的点击 全选/反选 单选框/复选框 文本框 表单验证
Jun 25 Javascript
简单对比分析JavaScript中的apply,call与this的使用
Dec 04 Javascript
javascript cookie的基本操作(添加和删除)
Jul 24 Javascript
20个最常见的jQuery面试问题及答案
May 23 jQuery
详解在React中跨组件分发状态的三种方法
Aug 09 Javascript
vue.js 2.0实现简单分页效果
Jul 29 Javascript
JS XMLHttpRequest原理与使用方法深入详解
Apr 30 Javascript
js实现上传图片到服务器
Apr 11 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
深入PHP5中的魔术方法详解
2013/06/17 PHP
PHP也能干大事之PHP中的编码解码详解
2015/04/20 PHP
Yii框架防止sql注入,xss攻击与csrf攻击的方法
2016/10/18 PHP
php使用PDO获取结果集的方法
2017/02/16 PHP
php中钩子(hook)的原理与简单应用demo示例
2019/09/03 PHP
High Performance JavaScript(高性能JavaScript)读书笔记分析
2011/05/05 Javascript
Ajax请求在数据量大的时候出现超时的解决方法
2014/02/27 Javascript
jQuery分组选择器用法实例
2014/12/23 Javascript
JavaScript编程中的Promise使用大全
2015/07/28 Javascript
详解JavaScript中数组和字符串的lastIndexOf()方法使用
2016/03/13 Javascript
angularJs关于指令的一些冷门属性详解
2016/10/24 Javascript
详解利用exif.js解决ios手机上传竖拍照片旋转90度问题
2016/11/04 Javascript
JS jQuery使用正则表达式去空字符的简单实现代码
2017/05/20 jQuery
想用好React的你必须要知道的一些事情
2017/07/24 Javascript
对vue.js中this.$emit的深入理解
2018/02/23 Javascript
Node.js的Koa实现JWT用户认证方法
2018/05/05 Javascript
JS闭包经典实例详解
2018/12/20 Javascript
vue实现微信分享链接添加动态参数的方法
2019/04/29 Javascript
Vue 幸运大转盘实现思路详解
2019/05/06 Javascript
更优雅的微信小程序骨架屏实现详解
2019/08/07 Javascript
nodejs+koa2 实现模仿springMVC框架
2020/10/21 NodeJs
[05:08]顺网杯ISS-DOTA2赛歌 少女偶像Lunar青春演绎
2013/12/05 DOTA
[06:13]DOTA2进化论(修改版)
2013/10/08 DOTA
Python使用matplotlib绘制正弦和余弦曲线的方法示例
2018/01/06 Python
对python中的iter()函数与next()函数详解
2018/10/18 Python
利用Python如何实现一个小说网站雏形
2018/11/23 Python
python3使用腾讯企业邮箱发送邮件的实例
2019/06/28 Python
python 表格打印代码实例解析
2019/10/12 Python
dpn网络的pytorch实现方式
2020/01/14 Python
Python新建项目自动添加介绍和utf-8编码的方法
2020/12/26 Python
html5中去掉input type date默认样式的方法
2018/09/06 HTML / CSS
婚纱店策划方案
2014/05/22 职场文书
幼儿教师求职信
2014/05/24 职场文书
财务管理专业求职信
2014/06/11 职场文书
因个人工作失误检讨书
2019/06/21 职场文书
Python实现生成bmp图像的方法
2021/06/13 Python