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 ...
随机推荐
- Http状态码(转)
什么是Http状态码?(转自http://bbs.tui18.com/thread-11597640-1-1.html) 百度百科上解释为:HTTP状态码(HTTP Status Code)是用以表示 ...
- asp值mysql驱动
http://www.sufeinet.com/thread-10278-1-1.html%20http://tool.sufeinet.com/CodePreview/CodeView.aspx?a ...
- delphi XE 5 Android 真机调试简易安装教程
① FireMonkey[DELPHI XE5]QQ群号:165232328,群内超过1600移动开发爱好者 第一步,打开手机中的USB调试 电脑自动装驱动,但是找不到 去手机官网下载驱动 手动安装驱 ...
- 介绍一个可以将Expression表达式树解析成Transact-SQL的项目Expression2Sql
一.Expression2Sql介绍 Expression2Sql是一个可以将Expression表达式树解析成Transact-SQL的项目.简单易用,几分钟即可上手使用,因为博主在设计Expres ...
- XML创建与解析常用方法介绍
XML解析方式介绍 1.DOM4J(Document Object Model for Java) 虽然DOM4J代表了完全独立的开发结果,但最初,它是JDOM的一种智能分支.它合并了许多超 ...
- 微信h5页面禁止下拉露出网页来源
1.可以给document的touchmove事件禁止掉就行了 document.querySelector('body').addEventListener('touchmove', functio ...
- drupal 7在一个form新增或者修改一个字段
例如在以下页面新增一个工号字段 在模块文件里面通过hook_form_FORM_ID_alter 函数修改,比如 图中的helloworld是模块名称,也就是你在哪个模块里面写这个函数那么名称就是什么 ...
- 【Android】解决新建的xml文件无法正常加载的问题
新建一个xml布局文件,如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xm ...
- c++ STL 学习记录 草稿。
非常丑陋的尝试实现stl.慢慢修改吧. 1)简单实现 vector和list. 2)思索如何开始编写算法. 1,所有容器继承一个抽象容器.那么算法就可以使用抽象基类的next方法来遍历元素. 容器间耦 ...
- JavaScript中有关数字的精确计算
问题这样的: 37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) ,我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998 怎么会 ...