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 相关文章推荐
响应鼠标变换表格背景或者颜色的代码
Mar 30 Javascript
javascript 节点遍历函数
Mar 28 Javascript
juqery 学习之五 文档处理 插入
Feb 11 Javascript
Js(JavaScript)中,弹出是或否的选择框示例(confirm用法的实例分析)
Jul 09 Javascript
一款jquery特效编写的大度宽屏焦点图切换特效的实例代码
Aug 05 Javascript
多种方法实现JS动态添加事件
Nov 01 Javascript
jQuery实现的网页竖向菜单效果代码
Aug 26 Javascript
基于JavaScript短信验证码如何实现
Jan 24 Javascript
解决拦截器对ajax请求的拦截实例详解
Dec 21 Javascript
PHP自动加载autoload和命名空间的应用小结
Dec 01 Javascript
使用jQuery动态设置单选框的选中效果
Dec 06 jQuery
微信小程序云函数使用mysql数据库过程详解
Aug 07 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
PHP实现MySQL更新记录的代码
2008/06/07 PHP
PHP使用xmllint命令处理xml与html的方法
2014/12/15 PHP
浅谈PHP发送HTTP请求的几种方式
2017/07/25 PHP
PHP基础之输出缓冲区基本概念、原理分析
2019/06/19 PHP
phpQuery采集网页实现代码实例
2020/04/02 PHP
JAVASCRIPT 对象的创建与使用
2021/03/09 Javascript
解决AJAX中跨域访问出现'没有权限'的错误
2008/08/20 Javascript
jquery实现的图片点击滚动效果
2014/04/29 Javascript
javascript对浅拷贝和深拷贝的详解
2016/10/14 Javascript
如何去除富文本中的html标签及vue、react、微信小程序中的过滤器
2018/11/21 Javascript
node.js的Express服务器基本使用教程
2019/01/09 Javascript
解决layui table表单提示数据接口请求异常的问题
2019/09/24 Javascript
vue+element表格导出为Excel文件
2019/09/26 Javascript
JavaScript实现页面高亮操作提示和蒙板
2021/01/04 Javascript
vue集成一个支持图片缩放拖拽的富文本编辑器
2021/01/29 Vue.js
在Python中封装GObject模块进行图形化程序编程的教程
2015/04/14 Python
Python3读取文件常用方法实例分析
2015/05/22 Python
利用Python实现命令行版的火车票查看器
2016/08/05 Python
python实现人脸识别经典算法(一) 特征脸法
2018/03/13 Python
Python3单行定义多个变量或赋值方法
2018/07/12 Python
Flask框架工厂函数用法实例分析
2019/05/25 Python
对Python函数设计规范详解
2019/07/19 Python
Python生成六万个随机,唯一的8位数字和数字组成的随机字符串实例
2020/03/03 Python
tensorflow实现残差网络方式(mnist数据集)
2020/05/26 Python
基于Keras中Conv1D和Conv2D的区别说明
2020/06/19 Python
Python3实现英文字母转换哥特式字体实例代码
2020/09/01 Python
python 密码学示例——理解哈希(Hash)算法
2020/09/21 Python
matplotlib之属性组合包(cycler)的使用
2021/02/24 Python
鼠标滚轮事件和Mac触控板双指事件
2019/12/23 HTML / CSS
质监局领导班子践行群众路线整改方案
2014/10/26 职场文书
业务员岗位职责
2015/02/03 职场文书
党课主持词大全
2015/06/30 职场文书
企业宣传稿范文
2015/07/23 职场文书
周末问候语大全
2015/11/10 职场文书
MySQL安装后默认自带数据库的作用详解
2021/04/27 MySQL
分享7个 Python 实战项目练习
2022/03/03 Python