Object-Oriented(二)原型对象
自用备忘笔记
1. 理解原型对象
只要创建函数,函数上就会创建一个 prototype 属性指向函数的原型对象。
function Person() {}
Person.prototype //指向该函数的原型对象
所有原型对象会自动获得一个 constructor 属性指向 prototype 属性所在的函数。
Person.prototype.constructor === Person; //true
每个通过构造函数生成的实例对象,都包含一个 [[Prototype]] 属性指向其构造函数的原型对象,在 Firefox、Safari 和 Chrome 中可以通过 __proto__ 来访问。
var Daryl = new Person();
Daryl.__proto__ === Person.prototype; //true
虽然无法通过标准的方法访问 [[Prototype]] 方法,但可以通过 isPrototypeOf() 方法来确实关系。
Person.prototype.isPrototypeOf(Daryl); //true
ES5新增了一个方法:Object.getPrototypeOf(),该方法可以返回 [[Prototype]] 的值。
Object.getPrototypeOf(Daryl) === Person.prototype; //true
虽然通过实例对象可以访问原型中的属性,但无法通过实例对象重写原型中的属性。
function Person() {}
Person.prototype.name = 'Daryl';
var person1 = new Person(),
person2 = new Person();
person1.name = 'Nicholas';
person1.name; //Nicholas
person2.name; //Daryl
对对象属性的访问,是先检索实例上有无该属性,再检索原型对象上有无该属性。若删除实例上的属性,则会恢复对原型对象属性的访问。
person1.name = 'Nicholas';
delete person1.name;
person1.name; //Daryl
通过 hasOwnProperty 方法可以检测某个属性究竟来自实例还是原型。
person1.name = 'Nicholas';
person1.hasOwnProperty('name'); //true
person2.hasOwnProperty('name'); //false
2. 原型与 in 操作符
in 操作符用来检测某个对象中是否有某个属性,可以单独使用,也可以搭配 for 使用。
person1.name = 'Nicholas';
'name' in person1; //true
'name' in person2; //true
使用 for-in 遍历对象的属性时会将原型上的属性一起遍历,如果需要滤掉这部分,可以搭配 hasOwnProperty 方法一起使用。
function Person() {}
Person.prototype.name = 'Nicholas';
var person = new Person();
person.age = 29;
person.gender = 'male';
for (var o in person) {
if (person.hasOwnProperty(o)) {
console.log(o); //age, gender
}
}
ES5新增了 Object.keys 方法,用来返回一个所有可枚举的实例属性的集合。
Object.keys(person); //['age', 'gender']
如果想要得到所有的属性,无论是否可枚举,可以使用 Object.getOwnPropertyNames。
Object.getOwnPropertyNames(Person.prototype); //['constructor', 'name']
以上两种方法都可以用来代替 for-in 循环。
3. 更简单的原型语法
为了避免重复书写,可以通过对象字面量的方式重写原型对象。
function Person() {}
Person.prototype = {
name: 'Nicholas',
age: 29,
sayName: function() {
alert(this.name);
}
};
这种方式会导致原型对象上的 constructor 属性丢失,可以手动指定 constructor 属性。
function Person() {}
Person.prototype = {
constructor: Person,
name: 'Nicholas',
age: 29,
sayName: function() {
alert(this.name);
}
};
但 constructor 本身是不可枚举的,可以通过 ES5 新增的 Object.defineProperty() 方法设置。
Object.defineProperty(Person.prototype, 'constructor', {
enumerable: false,
value: Person
});
4. 原型的动态性
由于在原型中查找值的过程是一次搜索,因此在任何时候对原型对象的修改都会立即反映在实例上。
var Daryl = new Person();
Person.prototype.sayHi = function() {
alert('Hi');
};
Daryl.sayHi(); //Hi
但是重写原型对象会导致构造函数与原型之间的联系被切断。
var Daryl = new Person();
Person.prototype = {
sayHi: function() {
alert('Hi');
}
};
Daryl.sayHi(); //出错
5. 原生对象的原型
原型模式不仅应用在自定义类型方面,就连所有原生的引用类型,都是采用这种模式创建的。它们都在其构造函数的原型上定义了方法。
Array.prototype.sort; //function
String.prototype.substring; //function
还可以在原生对象上定义新方法,如下,定义一个反转字符串的方法。
String.prototype.reverseString = function() {
return this.split('').reverse().join('');
};
'Hello World!'.reverseString(); //!dlroW olleH
6. 原型的问题
由于原型上所有属性均是共享的,若某个实例对原型中的引用类型属性进行修改,则这一个修改会反映在所有实例上。
function Person() {}
Person.prototype.friends = ['Shelby', 'Court'];
var person1 = new Person(),
person2 = new Person();
person1.friends.push('Van');
person2.friends; //['Shelby', 'Court', 'Van'];
Object-Oriented(二)原型对象的更多相关文章
- javaScript系列 [03]-javaScript原型对象
[03]-javaScript原型对象 引用: javaScript是一门基于原型的语言,它允许对象通过原型链引用另一个对象来构建对象中的复杂性,JavaScript使用原型链这种机制来实现动态代理. ...
- JavaScript基础之原型对象和原型链
原型对象 原型对象简单来说就是函数的原型所指向的对象.前面说原型的时候,说了Object.prototype所指对象就是Object(函数)的原型对象.在每个函数的原型对象中,默认会有construc ...
- 面对对象编程(OOP, Object Oriented Programming)及其三个基本特性
一千个读者,一千个哈姆雷特.对于面对对象编程,书上都会告诉我们它有三个基本特性,封装,继承,多态,但谈起对这三点的见解,又是仁者见仁智者见智,感觉还是得多去编程中体验把 . 面向对象编程(OOP, O ...
- DOM笔记(十二):又谈原型对象
因为之前谢过一篇关于原型对象的笔记:浅谈JavaScript中的原型模式.现在我又重新看到这个话题,对原型有了进一步的理解,所以,又要谈谈原型对象. 一.理解原型对象 创建的每一个函数都有一个prot ...
- web前端学习(二) javascript对象和原型继承
目录 1. JavaScrpt对象 2. 原型对象和继承 3. 对象的克隆 (1)javascript对象 在JS中,对象是属性的容器.对于单个对象来说,都由属性名和属性值构成:其中属性名需要是标识符 ...
- JavaScript之面向对象学习二(原型属性对象与in操作符)获取对象中所有属性的方法
1.原型属性对象于in操作符之in单独使用 有两种方式使用in操作符:单独使用和在for-in循环中使用.在单独使用中,代码如下: function Person(){ } Person.protot ...
- Vue源码学习二 ———— Vue原型对象包装
Vue原型对象的包装 在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式.在使用前都通过 new Vue({}).记录一下 Vue构造函数的包装. 在 src/core/in ...
- OO开发思想:面向对象的开发方法(Object oriented,OO)
面向对象的开发方法(Object oriented,OO)认为是好文章吧,拿来分享一下(转载) 面向对象的开发方法(Object oriented,OO) 从事软件开发的工程 师们常常有这样 的体会: ...
- 秒懂JS对象、构造器函数和原型对象之间的关系
学习JS的过程中,想要掌握面向对象的程序设计风格,对象模型(原型和继承)是其中的重点和难点,拜读了各类经典书籍和各位前辈的技术文章,感觉都太过高深,花费了不少时间才搞明白(个人智商是硬伤/(ㄒoㄒ)/ ...
随机推荐
- 手动将经典 VM 从 VHD 迁移到新的 ARM 托管磁盘 VM
本部分有助于将现有 Azure VM 从经典部署模型迁移到资源管理器部署模型中的托管磁盘. 计划迁移到托管磁盘 本部分可帮助你针对 VM 和磁盘类型做出最佳决策. 位置 选取 Azure 托管磁盘可用 ...
- Linux 查看本机串口方法
最近在了解嵌入式方面的知识,就随笔记录一下: 查看Linux本机串口: 1.查看串口是否可用 可以对串口发送数据比如对com1口,echo /dev/ttyS02.查看串口名称使用 ls -l /de ...
- 使用虚拟环境virtualenv/Virtualenvwrapper隔离多个python
virtualenv 系统中的多个python混用会导致$PYTHONPATH混乱,或者各个工程对于package的版本要求不同等等情况.有一个简单的解决方案就是用virtualenv来隔离多个pyt ...
- Github API
Web API web api是网站的一部分,用于与使用非常具体的URL请求特定信息的程序交互,这种请求被称为API调用.请求的数据将以易于处理的格式(如JSON或CSV)返回:依赖于外部数据源的大多 ...
- Linux运维之如何查看目录被哪些进程所占用,lsof命令、fuser命令
之前将一块硬盘挂载到某个目录下,但是现在我想卸载掉这块硬盘,无论如何都umount不了,有些同学可能说需要加上 -f 参数强制卸载,理论上是可以的,但是在我这里依然不起作用,比如: [root@:vg ...
- vSphere ESXi 重新安装后的虚拟机恢复(转载)
安装的 ESXi 的物理主机密码忘记,登录 不上了,需要重新安装 ESXi,安装后恢复原先物理主机上的 虚拟机的方法如下(VMFS分区完好): 关于 VMFS 分区: ESXi 的安装时会划分一个分区 ...
- beta版本汇总
deta版本五天汇总 day1 day2 day3 day4 day5 GitHub地址 前端代码github地址 后端代码github地址 这里说明一下我们队伍的安排风格: 第一天:明确安排前后端的 ...
- centos7下安装docker(13.3volume生命周期管理)
本章讨论:volume的备份,恢复,迁移和销毁 1.备份 通过前面的大量的实验,我们知道volume 是依赖host存在的,是host中的文件或目录,所以volume 的备份实际是对文件系统的备份. ...
- CF1045G:AI robots(CDQ分治)
Description 火星上有$n$个机器人排成一行,第$i$个机器人的位置为$x_i$,视野为$r_i$,智商为$q_i$.我们认为第$i$个机器人可以看到的位置是$[x_i−r_i,x_i+ ...
- 修改CentOS 7.2系统的主机名
之前使用网上的大部分说法,修改了两个配置文件: /etc/hosts /etc/sysconfig/network 然后,并没有什么卵用. 后来,搜阿里云配置,看到这个办法: 使用“经典网络”类型的E ...