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 相关文章推荐
新浪刚打开页面出来的全屏广告代码
Apr 02 Javascript
javascript 解析url的search方法
Feb 09 Javascript
javascript预览上传图片发现的问题的解决方法
Nov 25 Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
Jan 13 Javascript
jQuery提交多个表单的小技巧
Jul 27 Javascript
JavaScript实现将数组数据添加到Select下拉框的方法
Aug 21 Javascript
javascript的正则匹配方法学习
Feb 24 Javascript
Web打印解决方案之普通报表打印功能
Aug 29 Javascript
Angular实现一个简单的多选复选框的弹出框指令实例
Apr 25 Javascript
es6学习笔记之Async函数基本教程
May 11 Javascript
Node.js 使用axios读写influxDB的方法示例
Oct 26 Javascript
vue自动化路由的实现代码
Sep 30 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
玛琪朵 Macchiato
2021/03/03 咖啡文化
用PHP实现弹出消息提示框的两种方法
2013/12/17 PHP
php判断手机访问还是电脑访问示例分享
2014/01/20 PHP
四种php中webservice实现的简单架构方法及实例
2015/02/03 PHP
PHP+Mysql+jQuery实现发布微博程序 php篇
2015/10/15 PHP
PHP时间类完整实例(非常实用)
2015/12/25 PHP
Javascript计算两个marker之间的距离(Google Map V3)
2013/04/26 Javascript
javascript事件函数中获得事件源的两种不错方法
2014/03/17 Javascript
JavaScript中document对象使用详解
2015/01/06 Javascript
js实现固定显示区域内自动缩放图片的方法
2015/07/18 Javascript
五种js判断是否为整数类型方式
2015/12/03 Javascript
图解js图片轮播效果
2015/12/20 Javascript
分步解析JavaScript实现tab选项卡自动切换功能
2016/01/25 Javascript
理解javascript封装
2016/02/23 Javascript
JavaScript解八皇后问题的方法总结
2016/06/12 Javascript
浅析Nodejs npm常用命令
2016/06/14 NodeJs
jQuery组件easyui对话框实现代码
2016/08/25 Javascript
BootStrap modal模态弹窗使用小结
2016/10/26 Javascript
jstree单选功能的实现方法
2017/06/07 Javascript
JS利用正则表达式实现简单的密码强弱判断实例
2017/06/16 Javascript
layer的prompt弹出框,点击回车,触发确定事件的方法
2019/09/06 Javascript
解决vue无法侦听数组及对象属性的变化问题
2020/07/17 Javascript
jquery自定义组件实例详解
2020/12/31 jQuery
vue watch监控对象的简单方法示例
2021/01/07 Vue.js
Python查询阿里巴巴关键字排名的方法
2015/07/08 Python
Python使用pymysql模块操作mysql增删改查实例分析
2019/12/19 Python
python实现tail实时查看服务器日志示例
2019/12/24 Python
Tensorflow分批量读取数据教程
2020/02/07 Python
HTML5如何实现元素拖拽
2016/03/11 HTML / CSS
HTML5在手机端实现视频全屏展示方法
2020/11/23 HTML / CSS
大三毕业自我鉴定
2014/01/15 职场文书
股权收购意向书
2014/04/01 职场文书
新颖的化妆品活动方案
2014/08/21 职场文书
2015年物业管理工作总结
2015/04/23 职场文书
全国助残日活动总结
2015/05/11 职场文书
家长会开场白和结束语
2015/05/29 职场文书