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 上下滚动广告
Jun 17 Javascript
解析Javascript中中括号“[]”的多义性
Dec 03 Javascript
判断某个字符在一个字符串中是否存在的js代码
Feb 28 Javascript
Node.js异步I/O学习笔记
Nov 04 Javascript
js对象继承之原型链继承实例
Jan 10 Javascript
DOM操作和jQuery实现选项移动操作的简单实例
Jun 07 Javascript
jQuery增加、删除及修改select option的方法
Aug 19 Javascript
js制作简单的音乐播放器的示例代码
Aug 28 Javascript
原生JS控制多个滚动条同步跟随滚动效果
Dec 22 Javascript
Vue多系统切换实现方案
Jun 05 Javascript
vue组件系列之TagsInput详解
May 14 Javascript
jQuery+Ajax+js实现请求json格式数据并渲染到html页面操作示例
Jun 02 jQuery
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实现支付宝即时到账功能
2016/12/21 PHP
PHP操作MySQL中BLOB字段的方法示例【存储文本与图片】
2017/09/15 PHP
php微信开发之关键词回复功能
2018/06/13 PHP
php-fpm中max_children的配置
2019/03/15 PHP
客户端静态页面玩分页
2006/06/26 Javascript
js导入导出excel(实例代码)
2013/11/25 Javascript
HTML页面弹出居中可拖拽的自定义窗口层
2014/05/07 Javascript
JavaScript导航脚本判断当前导航
2016/07/12 Javascript
完美JQuery图片切换效果的简单实现
2016/07/21 Javascript
玩转NODE.JS(四)-搭建简单的聊天室的代码
2016/11/11 Javascript
详解vue-Resource(与后端数据交互)
2017/01/16 Javascript
JSON键值对序列化和反序列化解析
2017/01/24 Javascript
详解vue数据渲染出现闪烁问题
2017/06/29 Javascript
深入理解vue中slot与slot-scope的具体使用
2018/01/26 Javascript
代码分析vue中如何配置less
2018/09/28 Javascript
微信小程序如何访问公众号文章
2019/07/08 Javascript
JQuery复选框全选效果如何实现
2020/05/08 jQuery
Python中最常用的操作列表的几种方法归纳
2015/04/24 Python
在Python中操作时间之strptime()方法的使用
2020/12/30 Python
解决Matplotlib图表不能在Pycharm中显示的问题
2018/05/24 Python
Python英文文本分词(无空格)模块wordninja的使用实例
2019/02/20 Python
更新pip3与pyttsx3文字语音转换的实现方法
2019/08/08 Python
Windows10下 python3.7 安装 facenet的教程
2019/09/10 Python
python 通过邮件控制实现远程控制电脑操作
2020/03/16 Python
python 6行代码制作月历生成器
2020/09/18 Python
CSS3中设置3D变形的transform-style属性详解
2016/05/23 HTML / CSS
美国紧身牛仔裤品牌:NYDJ
2017/05/24 全球购物
银行学习十八大感想
2014/01/11 职场文书
中学优秀班主任事迹材料
2014/05/01 职场文书
酒店节能降耗方案
2014/05/08 职场文书
小学生民族团结演讲稿
2014/08/27 职场文书
高校教师个人总结
2015/02/10 职场文书
幼儿园新学期开学寄语
2015/05/27 职场文书
2015国庆节宣传语
2015/07/14 职场文书
学校学期工作总结
2015/08/13 职场文书
git中cherry-pick命令的使用教程
2022/06/25 Servers