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 相关文章推荐
Draggable Elements 元素拖拽功能实现代码
Mar 30 Javascript
用Juery网页选项卡实现代码
Jun 13 Javascript
jquery Mobile入门—外部链接切换示例代码
Jan 08 Javascript
jquery的冒泡事件的阻止与允许(三种实现方法)
Feb 01 Javascript
Jquery动态添加及删除页面节点元素示例代码
Jun 16 Javascript
javascript实现数独解法
Mar 14 Javascript
JavaScript如何实现组合列表框中元素移动效果
Mar 01 Javascript
jQuery使用deferreds串行多个ajax请求
Aug 22 Javascript
JavaScript数据结构学习之数组、栈与队列
May 02 Javascript
js实现单张图片平移切换效果
Oct 11 Javascript
vue router+vuex实现首页登录验证判断逻辑
May 17 Javascript
Node.js系列之发起get/post请求(2)
Aug 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
初级的用php写的采集程序
2007/03/16 PHP
一个JavaScript继承的实现
2006/10/24 Javascript
有关DOM元素与事件的3个谜题
2010/11/11 Javascript
Eclipse去除js(JavaScript)验证错误
2014/02/11 Javascript
Javascript+CSS实现影像卷帘效果思路及代码
2014/10/20 Javascript
js 求时间差的实现代码
2016/04/26 Javascript
Javascript HTML5 Canvas实现的一个画板
2020/04/12 Javascript
微信小程序动态显示项目倒计时效果
2017/06/13 Javascript
vue的基本用法与常见指令
2017/08/15 Javascript
angular实现input输入监听的示例
2018/08/31 Javascript
VUE DOM加载后执行自定义事件的方法
2018/09/07 Javascript
layer弹出子iframe层父子页面传值的实现方法
2018/11/22 Javascript
在vue使用clipboard.js进行一键复制文本的实现示例
2019/01/15 Javascript
Vue组件间通信 Vuex的用法解析
2019/08/05 Javascript
原生js无缝轮播插件使用详解
2020/03/09 Javascript
微信小程序学习总结(五)常见问题实例小结
2020/06/04 Javascript
[19:15]DK战队纪录片
2014/09/02 DOTA
Python中生成Epoch的方法
2017/04/26 Python
TensorFlow 滑动平均的示例代码
2018/06/19 Python
Python实现的绘制三维双螺旋线图形功能示例
2018/06/23 Python
python递归实现快速排序
2018/08/18 Python
Python WEB应用部署的实现方法
2019/01/02 Python
Python中包的用法及安装
2020/02/11 Python
python实现文法左递归的消除方法
2020/05/22 Python
详解python实现可视化的MD5、sha256哈希加密小工具
2020/09/14 Python
python 实现音频叠加的示例
2020/10/29 Python
夏洛特和乔治婴儿和儿童时装精品店:Charlotte and George
2018/06/06 全球购物
期末考试动员演讲稿
2014/01/10 职场文书
银行领导证婚词
2014/01/11 职场文书
公司门卫岗位职责
2014/03/15 职场文书
创先争优个人总结
2015/03/04 职场文书
2015年学校总务处工作总结
2015/05/19 职场文书
妈妈别哭观后感
2015/06/08 职场文书
运动会主持人开幕词
2016/03/04 职场文书
自荐信范文
2019/05/20 职场文书
Python实现8种常用抽样方法
2021/06/27 Python