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的表格操作插件
Apr 22 Javascript
js 全兼容可高亮二级缓冲折叠菜单
Jun 04 Javascript
判断浏览器的javascript版本的代码
Sep 03 Javascript
node.js中的require使用详解
Dec 15 Javascript
jQuery中click事件用法实例
Dec 26 Javascript
jQuery EasyUI datagrid实现本地分页的方法
Feb 13 Javascript
JavaScript设置、获取、清除单值和多值cookie的方法
Nov 17 Javascript
vue 2.0组件与v-model详解
Mar 27 Javascript
深入理解JavaScript创建对象的多种方式以及优缺点
Jun 01 Javascript
jquery图片放大镜效果
Jun 23 jQuery
jQuery分组选择器简单用法示例
Apr 04 jQuery
JSON是什么?有哪些优点?JSON和XML的区别?
Apr 29 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 cookie 作用范围?不要在当前页面使用你的cookie
2009/03/24 PHP
JavaScript关于select的相关操作说明
2010/01/13 Javascript
基于Jquery的$.cookie()实现跨越页面tabs导航实现代码
2011/03/03 Javascript
JS 无限级 Select效果实现代码(json格式)
2011/08/30 Javascript
鼠标悬停小图标显示大图标
2016/01/22 Javascript
vue实现添加标签demo示例代码
2017/01/21 Javascript
JS实现的DIV块来回滚动效果示例
2017/02/07 Javascript
浅谈js中function的参数默认值
2017/02/20 Javascript
vue-cli单页应用改成多页应用配置详解
2017/07/14 Javascript
vue解决一个方法同时发送多个请求的问题
2018/09/25 Javascript
vue实现图片预览组件封装与使用
2019/07/13 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
手把手带你搭建一个node cli的方法示例
2020/08/07 Javascript
jQuery实现电梯导航模块
2020/12/22 jQuery
跟老齐学Python之Python文档
2014/10/10 Python
python中pylint使用方法(pylint代码检查)
2018/04/06 Python
详解Python sys.argv使用方法
2019/05/10 Python
python3 反射的四种基本方法解析
2019/08/26 Python
python绘制彩虹图
2019/12/16 Python
Python字符串、列表、元组、字典、集合的补充实例详解
2019/12/20 Python
如何使用PyCharm引入需要使用的包的方法
2020/09/22 Python
HTML5实现Notification API桌面通知功能
2016/03/02 HTML / CSS
澳大利亚潮流尖端的快时尚品牌:Cotton On
2016/09/26 全球购物
Becextech新西兰:数码单反相机和手机在线商店
2018/04/27 全球购物
世界上第一个创建了罩杯系统的美国内衣品牌:Maidenform
2019/03/23 全球购物
英国名牌服装购物网站:OD’s Designer
2019/09/02 全球购物
Timberland俄罗斯官方网上商店:全球领先的户外品牌
2020/03/15 全球购物
捷克家电和家具购物网站:OKAY.cz
2020/07/23 全球购物
The North Face官方旗舰店:美国著名户外品牌
2020/09/28 全球购物
入党申请自荐书范文
2014/02/11 职场文书
学生会招新策划书
2014/02/14 职场文书
工商行政管理专业求职书
2014/05/23 职场文书
店铺转让协议书(2014版)
2014/09/23 职场文书
优秀党员事迹材料
2014/12/18 职场文书
白银帝国观后感
2015/06/17 职场文书
springboot使用Redis作缓存使用入门教程
2021/07/25 Redis