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 相关文章推荐
jquery $(&quot;#variable&quot;) 循环改变variable的值示例
Feb 23 Javascript
js的参数有长度限制吗?发现不能超过2083个字符
Apr 20 Javascript
Js+php实现异步拖拽上传文件
Jun 23 Javascript
node.js抓取并分析网页内容有无特殊内容的js文件
Nov 17 Javascript
在WordPress中加入Google搜索功能的简单步骤讲解
Jan 04 Javascript
js中scrollTop()方法和scroll()方法用法示例
Oct 03 Javascript
Jquery删除css属性的简单方法
Dec 04 Javascript
VUE 更好的 ajax 上传处理 axios.js实现代码
May 10 Javascript
超级简易的JS计算器实例讲解(实现加减乘除)
Aug 08 Javascript
原生JS控制多个滚动条同步跟随滚动效果
Dec 22 Javascript
Vue之Vue.set动态新增对象属性方法
Feb 23 Javascript
微信小程序实现漂亮的弹窗效果
May 26 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
判“新”函数:得到今天与明天的秒数
2006/10/09 PHP
用文本文件制作留言板提示(上)
2006/10/09 PHP
CakePHP去除默认显示的标题及图标的方法
2008/10/22 PHP
ThinkPHP权限认证Auth实例详解
2014/07/22 PHP
jquery蒙版控件实现代码
2010/12/08 Javascript
读jQuery之五(取DOM元素)
2011/06/20 Javascript
javascript中闭包(Closure)详解
2016/01/06 Javascript
jQuery通过ajax方法获取json数据不执行success的原因及解决方法
2016/10/15 Javascript
利用canvas实现的加载动画效果实例代码
2017/07/05 Javascript
使用live-server快速搭建本地服务器+自动刷新的方法
2018/03/09 Javascript
手把手带你封装一个vue component第三方库
2019/02/14 Javascript
javascript中的闭包概念与用法实践分析
2019/07/26 Javascript
微信小程序之 catalog 切换实现解析
2019/09/12 Javascript
原生js实现日历效果
2020/03/02 Javascript
JavaScript组合模式---引入案例分析
2020/05/23 Javascript
vue编写简单的购物车功能
2021/01/08 Vue.js
[00:58]2016年国际邀请赛勇士令状宣传片
2016/06/01 DOTA
python使用any判断一个对象是否为空的方法
2014/11/19 Python
详解Python实现按任意键继续/退出的功能
2016/08/19 Python
Python绘制并保存指定大小图像的方法
2019/01/10 Python
python通过配置文件共享全局变量的实例
2019/01/11 Python
Python解析命令行读取参数之argparse模块
2019/07/26 Python
Python3 使用selenium插件爬取苏宁商家联系电话
2019/12/23 Python
python实现邮件循环自动发件功能
2020/09/11 Python
函授本科毕业生自我鉴定
2013/10/16 职场文书
社区道德讲堂实施方案
2014/03/21 职场文书
教师中国梦演讲稿
2014/04/23 职场文书
学生会生活部工作总结2015
2015/03/31 职场文书
企业财务人员岗位职责
2015/04/14 职场文书
交通事故调解协议书
2015/05/20 职场文书
宝宝满月祝酒词
2015/08/10 职场文书
2015年教师节广播稿
2015/08/19 职场文书
岗位聘任协议书
2015/09/21 职场文书
教师实习自我鉴定总结
2019/08/20 职场文书
Redis过期数据是否会被立马删除
2022/07/23 Redis
Go gorilla securecookie库的安装使用详解
2022/08/14 Golang