javascript中对象在OOP方面的一些知识(主要是prototype和__proto__相关)
在ES6的Class到来之前,先总结下个人对js中prototype属性的理解。
1、构造函数(大写函数名 this 无return) 2、原型对象(函数.prototype) 3、实例对象( new出来的东西obj )
备注:本文举例子都以Fn作为构造函数 Fn.prototype作为原型对象 实例对象obj = new Fn()
构造函数中的this是指向window的,只有用了new方法来调用,它才成为了构造函数,new调用时候发生了this指向的改变,指向了实例对象。

为什么会引出prototype这个东东(这个属性是一个指针,指向一个对象)??
因为:1、每次new实例的时候,都会创建内部的所有属性和方法 --- 很浪费
2、每次new出来的实例对象 他们并不相等 --- 比较的是指针,指针并不相等
所以:把其公用的(什么叫公用的,就是每个new出对象都需要的)属性和方法写在原型对象prototype上,(构造函数和原型对象由指针指向关系)
这样即可保证只有一次的创建(节省性能) 还可以保证 实例对象 的指针相同,也就是他们相同
谁有prototype这个属性? 每个函数都有 通过Function.prototype.bind方法构造出来的函数是个例外,它没有prototype属性
谁有__proto__属性? 每个对象都有(函数也是对象,所以函数也有此属性) 一个对象的隐式原型 指向 构造该对象的构造函数的原型
函数的__proto__ 属性例子: function F(){};console.log(F.__proto__ === Function.prototype)
谁有constructor这个属性? 每个对象都有,因为此属性是Obejct有的,在其他对象的原型链上,继承过来的
所以说构造函数原型属性prototype上两个很独特的自带属性就是constructor和__proto__。

2、内建对象的构造器函数



3、原型的动态性:
动态性和new创建的时机无关,不管修改prototype和new谁先谁后(前提是不要重写):
我们对 原型对象prototype 所做的任何修改都能够立即从 实例obj 上反映出来—— 即使是先创建了实例后修改(而不是后创建)原型也照样如此,后创建叫做重写原型对象
实例与原型之间的连接只不过是一个指针,松散连接。 请记住:实例中的指针仅指向原型,而不指向构造函数。
调用构造函数时会为实例添加一个指向最初原型的__Prototype__ 指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。。

可以看出早以前创建的实例friend还依旧指向最初的person.prototype,在后面重写了person.prototype,而friend指针却没变,依旧指向了旧的。
正所谓 一颗赤心向明月,奈何过往已惘然,独守空城遥遥望,不知去日不可覆。
说明了:修改属性可以获得动态改变,但一旦重写了,新功能已然与你无关,不在同一世界了,往事已切断
如果此时在new新的对象,那么新的对象的__proto__是指向新的,和旧的对象指向不是同一个prototype。那么也可以看出,动态性和重写是两个不相关的东西,不能混为一谈
注意Fn.prototype添加(归于修改里面)和重写带来的影响
添加:Fn.prototype.aaaa = function XXX(){} 添加:这个是挂接,挂接前后 obj.__proto__ === Fn.prototype === obj.constructor.prototype
重写:Fn.prototype = { aaaa : function XXX(){}} 重写:这个是赋值 赋值以后 obj.__proto__ === Fn.prototype !== obj.constructor.prototype,
因为此时Fn.prototype的constructor属性指向了Object。

最常规的写法(有个致命的问题):
function Person(){}
Person.prototype = {
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {alert(this.name);}
};
var boy = new Person();
结论: boy instanceof Person // true boy instanceof Object // true boy.constructor === Object // true boy.constructor === Person // false
说明了 Person.prototype = {key : value}这种事粗暴的重写,破坏了__Prototype__ 指针,需要补救
方法1、在最后补上 Person = Person.prototype.constructor
方法2、在对象内部填上constructor属性,以这种方式重设 constructor 属性会导致它的 [[Enumerable]] 特性被设置为 true。
Person.prototype = {
constructor : Person,
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {alert(this.name);}
};
方法3: Object.defineProperty()
Object.defineProperty(Person.prototype, "constructor", {
enumerable: false,
value: Person
});
最正确的但是比较繁琐的是给Person.prototype添加属性和方法(修改)
如:Person.prototype.name = "Nicholas"
.........
Person.prototype.sayName = function () {alert(this.name);}
属性查找和删除属性
找属性的时候,先找本身的,有的话就使用,没有的话层层上找。对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性,记住是屏蔽而不是修改
删除本身属性 可用delete方法来删除 得到的都是原型链继承来的属性 ,delete并不能删除原型链上的属性和方法,只能删除对象自己挂接的
4、钩子,原型链(也称__proto__链)
__proto__钩子指向谁(看此对象的创建方式,分三种)???

原型链:
js中万物皆对象,__proto__是所有对象都有的属性,所以可以从最开始的obj通过__proto__钩子连接,直到最后的null
读取对象属性/方法沿着原型链的走势:会先看当前对象中是否有这个属性,如果没有的话,就会查找它的prototype对象是否有这个属性,如此递推下去,一致检索到Object内建对象。

javascript中对象在OOP方面的一些知识(主要是prototype和__proto__相关)的更多相关文章
- 【你不知道的javaScript 上卷 笔记7】javaScript中对象的[[Prototype]]机制
[[Prototype]]机制 [[Prototype]]是对象内部的隐试属性,指向一个内部的链接,这个链接的作用是:如果在对象上没有找到需要的属性或者方法引用,引擎就 会继续在 [[Prototyp ...
- javascript中对象字面量的理解
javascript中对象字面量与数组字面量 第一部分 我们知道JavaScript中的数据类型有基本数据类型和引用类型,其中Object类型就是非常常用的类型.那么如果创建一个Object类型的实例 ...
- 关于JavaScript中对象的继承实现的学习总结
一.原型链 JavaScript 中原型链是实现继承的主要方法.其主要的思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.实现原型链有一种基本模式,其代码如下. function Super ...
- javascript中对象的深度克隆
记录一个常见的面试题,javascript中对象的深度克隆,转载自:http://www.2cto.com/kf/201409/332955.html 今天就聊一下一个常见的笔试.面试题,js中对象的 ...
- JavaScript中对象的属性
在JavaScript中,属性决定了一个对象的状态,本文详细的研究了它们是如何工作的. 属性类型 JavaScript中有三种不同类型的属性:命名数据属性(named data properties) ...
- JavaScript中对象转换为原始值的规则
JavaScript中对象转换为原始值遵循哪些原则? P52 对象到布尔值对象到布尔值的转换非常简单:所有的对象(包括数字和函数)都转换为true.对于包装对象亦是如此:new Boolean(fal ...
- JavaScript中对象的含义与this的指向
JavaScript中的对象:无序属性的集合 -其属性可以包含基本值.对象或函数.对象就是一组没有顺序的值.我们可以吧JavaScript中的对象想象成键值对,其中值可以是数据和函数.对象的行为和特征 ...
- Javascript中对象的Obeject.defineProperty()方法-------------(ES5/个人理解)
在讲到Obeject.defineProperty()方法之前先得说明一下ECMAScript中有两种属性:数据属性和访问器属性. 两种属性存在的意义:描述对象属性(key)的一些特性,因为这些属性是 ...
- javascript中对象的不同创建方法
javascript中的对象与一般的面向对象的程序设计语言(c++,Java等)不同,甚至很少有人说它是面向对象的程序设计语言,因为它没有类.javaScript只有对象,不是类的实例.javascr ...
随机推荐
- 我的Android第三章
先看效果图. 点击之后出变成 按钮内容改变了,并且弹出一个小提示 下面我们就来看看如何实现这个小案例 1)先打开string.xml文件,把要定义的字符串资源放置在里面 2)然后我们要画页面,基本An ...
- thinkphp 查询当天 ,本周,本月,本季度,本年度,全部, 数据方法
数据库字段是createtime 里面保存的是时间戳 <?php /* *按今天,本周,本月,本季度,本年,全部查询预约单数据 * $day 代表查询条件 $cid 代表 公司id *返回arr ...
- Unity四元数小问题整理
1.Unity中,四元数不能保存超过360度的旋转,所以如此大范围的旋转不能直接两个四元数做插值(当你用0度和721度的四元数做插值,它只会转1度,而不会转两圈). 2.要把旋转设置成某个方向,用Lo ...
- 【前端】提取URL中的各个GET参数
/**************************** * 有这样一个URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xx ...
- 走进java对象的门口
从题目中可以看出来,今天只是java面向对象的入门级探讨.看看今天的内容.
- json接口
http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?apikey=7waqfqbprs7pajbz2 ...
- 如何将推送证书p12导出为pem
1. 在Mac上启动Keychain助手,然后在login keychain中选择 Certificates分类.你将看到一个可展开的“Apple Development Push Services” ...
- HTML特殊转义字符列表
HTML特殊转义字符列表 最常用的字符实体 显示 说明 实体名称 实体编号 空格 < 小于 < < > 大于 > > & ...
- React组件库
图表组件库:Recharts(React和D3构建的图表库) UI组件库:react-bootstrap
- 图片的DataURL技术
DataURL基本原理 在网页中我们通常用下面的方式来引用一张图片,这样当我们请求网页的时候,浏览器也会想服务器发起一个请求,去请求这张图片. <img src='images/test.jpg ...