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 ...
随机推荐
- CryptoJS DES加密
<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equ ...
- Android Paint的属性
在Paint中有很多的属性可以设置,比如可以设置阴影,颜色过滤等等,这些会产生不同的奇妙效果,今天就对各种属性探索一下. 方法一: 1 //设置绘制的颜色,a代表透明度,r,g,b代表颜色值. 2 s ...
- 开发工具&环境
远程拷贝:scp cdh4.tar.gz root@10.239.44.111 ~ gerrit for code review: git add . git commit -a git push o ...
- JavaScript的chapterII
程序流程控制: 1.条件语句——if if(condition) {statement1} else {statement2} 例子: if(i<60 && ...
- BLE编程中关键步骤
获取权限 <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permiss ...
- Java时间的处理
1. Java计算时间依靠1970年1月1日开始的毫秒数.2. Date类的构造函数Date()返回代表当前创建的时刻的对象.Date的方法getTime()返回一个long值在数值上等于1970年1 ...
- Android TabHost使用
TabHost是Android中自带的选项卡控件,效果图如下: 主布局文件 <RelativeLayout xmlns:android="http://schemas.android. ...
- 一句话简单理解javascript中的原型对象
通过构造函数F创建的对象实例p 这个对象p的原型对象是 构造函数中prototype属性指向的对象s,这个对象p中也有个非标准的__proto__属性指向构造函数prototype属性所指向的对象s, ...
- matlab 视频转换到图像并保存
图像处理中像Adas.车辆检测等都需要采用视频文件比较好处理一点,利用帧差法.背景减法.光流法等,那么将视频文件转换到图像文件怎么做呢?话不多说,见代码一目了然: %================= ...
- JS控制TABLE表格在任意一行下面添加一行(有待完善)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...