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 ...
随机推荐
- YTU 3027: 哈夫曼编码
原文链接:https://www.dreamwings.cn/ytu3027/2899.html 3027: 哈夫曼编码 时间限制: 1 Sec 内存限制: 128 MB 提交: 2 解决: 2 ...
- 向STM32 CUBE MX 生成的工程里移植stemwin
我参考这个文章做的: http://bbs.armfly.com/read.php?tid=1678 这次添加的是没有os的版本 另外跟用不用hal库没关系 1. keil自带了emwin 2. 用c ...
- ADO 读取 ACCESS
#pragma once #include <vector> // 加入ADO支持库, #import "C:\Program Files\Common Files\System ...
- Mybatis映射文件
Mapper XML 文件 MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会 ...
- 第一个python实例--监控cpu
#第一个python实例:监控cpu #/bin/bash/env Python from __future__ import print_function from collections impo ...
- sqoop的使用
1.sqoop的安装 1.1 与hadoop和hive的集成,修改/opt/cdh/sqoop-1.4.5-cdh5.3.6/conf/sqoop-env.sh 文件
- SQL 存储过程 分页查询
ALTER PROCEDURE [dbo].[gzProc_TablePage] @tablename varchar(MAX),--表名 @selcolumn varchar(MAX),--查询字段 ...
- GitHub注册账号
username : hcloudypassword : hujunyun3174email : 370284221@qq.com
- php : 常用函数
常用函数: <?php /** * 获取客户端IP * @return [string] [description] */ function getClientIp() { $ip = NULL ...
- rxjava源码中的线程知识
rxjava源码中的线程知识 rx的最精简的总结就是:异步 这里说一下以下的五个类 1.Future2.ConcurrentLinkedQueue3.volatile关键字4.AtomicRefere ...