标签:alt 分享 height class 找对象 其他属性 自定义 构造 prot
/** * 原型对象 * 无论什么时,只要创建一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性 * 这个属性就是原型对象。默认情况下,所有原型对象都会自动获得一个 constructor(构造函数) * 属性,这个属性包含一个指向 prototype 属性所在函数的指针。当构造函数创建一个新实例后, * 该实例的内部包含一个指针[[Prototype]](内部属性),指向构造函数的原型对象。 */ /** * 如: * 创建一个函数 A:function A(){} * function A(){} 会有一个属性: prototype 属性 * function A(){} 的原型对象为: A.prototype * function A(){} 的原型对象会自动获得一个 constructor 属性: A.prototype.constructor * 那么: * function A(){} 中的 prototype 属性 ---(指向)---> A.prototype (function A(){} 的原型对象) * A.prototype.constructor (constructor属性) ---(指向)---> function A(){} (函数 A) */ function A(){} console.log(A.prototype.constructor==A);//true 可见原型对象中的 constructor 指向函数A /** * 如: * 使用 new 关键字结合 A() 函数来创建实例 obj * 则 obj 这个实例会有一个 [[Prototype]] 内部属性指向 A 的原型对象 A.prototype * Firefox、Safari 和Chrome 在每个对象上都支持一个属性 __proto__ ,它就相当于 [[Prototype]] */ var obj=new A(); console.log(obj.__proto__==A.prototype);//true 可见实例中的 [[Prototype]] 指向函数原型 A.prototype A.prototype.name="guang";//给A的原型对象增加一个name:"guang"属性 A.prototype.sayName=function(){return this.name};//给A的原型对象增加一个sayName方法 var obj=new A(); console.log(obj.sayName());//guang
// 上图展示了A 构造函数、A 的原型属性以及A 现有的实例 obj之间的关系。 // 在此,A.prototype 指向了原型对象,而A.prototype.constructor 又指回了A。 // 原型对象中除了包含constructor 属性之外,还包括后来添加的其他属性。A 的每个实例— // 都包含一个内部属性,该属性仅仅指向了 A.prototype原型对象,而构造函数没有直接的关系。 // 虽然这 obj实例不包含属性和方法,但却可调用 A.sayName(),这是通过查找对象属性的过程来实现的。 // 每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先 // 从对象实例本身开始。如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到, // 则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到了这 // 个属性,则返回该属性的值。 // 对于上面的例子而言,在调用A.sayName()的时候,会先后执行两次搜索 // 首先,解析器会问:“实例A 有sayName 属性吗?”答:“没有。”然后,它继续搜索,再 // 问:“A 的原型有sayName 属性吗?”答:“有。”于是,它就读取那个保存在原型对象中的函数。 // 而这正是多个对象实例共享原型所保存的属性和方法的基本原理。
/** * 原型链 * 每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。 * 当一个原型对象是另一个原型对象的实例时,该原型对象将包含一个指向另一个原型的指针。相应地,另一个原型中也包含着一个指向 * 另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条 */ function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function (){ return this.subproperty; }; var instance = new SubType(); console.log(instance.getSuperValue()); //true //以上代码定义两个类型:SuperType、SubType。通过创建 SuperType的实例,原型对象 SubType.prototype 继承了SuperType的属性 //本质上是通过重写原型对象实现继承。如图:
// 在上面的代码中,并没有使用SubType 默认提供的原型,而是给它换了一个新原型;这个新原型 // 就是SuperType 的实例。于是,新原型不仅具有作为一个SuperType 的实例所拥有的全部属性和方法, // 而且其内部还有一个指针,指向了SuperType 的原型。 // 最终结果就是这样的:instance 指向SubType的原型, SubType 的原型又指向SuperType 的原型。 // getSuperValue() 方法仍然还在 SuperType.prototype 中,但property 则位于SubType.prototype 中。 // 这是因为property 是一个实例属性,而getSuperValue()则是一个原型方法。既然SubType.prototype 现在是SuperType // 的实例,那么property 当然就位于该实例中了。此外,要注意instance.constructor 现在指向的 // 是SuperType,这是因为SubType 的原型指向了另一个对象——>SuperType 的原型,而这个原型对象的constructor 属性指向的是SuperType。 // 在通过原型链实现继承的情况下,搜索过程就得以沿着原型链继续向上。就拿上面的例子来说,调用 // instance.getSuperValue()会经历三个搜索步骤:1>搜索实例;2>搜索SubType.prototype;3>搜索SuperType.prototype, // 4>最后一步才会找到该方法。在找不到属性或方法的情况下,搜索过程总是要一环一环地前行到原型链末端才会停下来。
// 事实上,因为所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object 的实例, // 因此默认原型都会包含一个内部指针,指向Object.prototype。这也正是所有自定义类型都会继承toString()、valueOf()等 // 默认方法的根本原因。对该例子来说完整的原型链应该如下:
//内置函数及其原型链
//上述图中的原型及原型链的关系图中, 将 String 换成 Array、Number、Boolean、及其他一些内置函数时,依然有类似的关系 //下面是与之相关的一些运行结果: console.log("XXX"); console.log("String:",String);//String: function String() 内置构造函数 console.log("Function:",Function);//Function: function Function() 内置构造函数 console.log("Object:",Object);//Object: function Object() 内置构造函数 console.log("Array:",Array);//Array: function Array() 内置构造函数 console.log("Number:",Number);//Number: function Number() 内置构造函数 console.log("Boolean:",Boolean);//Boolean: function Boolean() 内置构造函数 console.log("XXX.prototype"); console.log("String.prototype:",String.prototype);//String.prototype: String { "" } 空字符串 console.log("Function.prototype:",Function.prototype);//Function.prototype: function () 空函数 console.log("Object.prototype:",Object.prototype);//Object.prototype: Object { … } 空对象 console.log("Array.prototype:",Array.prototype);//Array.prototype: Array [] 空数组 console.log("Number.prototype:",Number.prototype);//Number.prototype: Number { 0 } 数字零 console.log("Boolean.prototype:",Boolean.prototype);//Boolean.prototype: Boolean { false } 布尔值 false console.log("XXX.prototype.constructor"); console.log("String.prototype.constructor:",String.prototype.constructor); //String.prototype.constructor: function String() 内置构造函数 console.log("Function.prototype.constructor:",Function.prototype.constructor); //Function.prototype.constructor: function Function() 内置构造函数 console.log("Object.prototype.constructor:",Object.prototype.constructor); //Object.prototype.constructor: function Object() 内置构造函数 console.log("Array.prototype.constructor:",Array.prototype.constructor); //Array.prototype.constructor: function Array() 内置构造函数 console.log("Number.prototype.constructor:",Number.prototype.constructor); //Number.prototype.constructor: function Number() 内置构造函数 console.log("Boolean.prototype.constructor:",Boolean.prototype.constructor); //Boolean.prototype.constructor: function Boolean() 内置构造函数 console.log("XXX.__proto__"); console.log("String.__proto__:",String.__proto__);//String.__proto__: function () 空函数 console.log("Function.__proto__:",Function.__proto__);//Function.__proto__: function () 空函数 console.log("Object.__proto__:",Object.__proto__);//Object.__proto__: function () 空函数 console.log("Array.__proto__:",Array.__proto__);//Array.__proto__: function () 空函数 console.log("Number.__proto__:",Number.__proto__);//Number.__proto__: function () 空函数 console.log("Boolean.__proto__:",Boolean.__proto__);//Boolean.__proto__: function () 空函数 console.log("XXX.prototype.__proto__"); console.log("String.prototype.__proto__:",String.prototype.__proto__); //String.prototype.__proto__: Object { … } 空对象 console.log("Function.prototype.__proto__:",Function.prototype.__proto__); //Function.prototype.__proto__: Object { … } 空对象 console.log("Object.prototype.__proto__:",Object.prototype.__proto__); //Object.prototype.__proto__: null 空对象 console.log("Array.prototype.__proto__:",Array.prototype.__proto__); //Array.prototype.__proto__: Object { … } 空对象 console.log("Number.prototype.__proto__:",Number.prototype.__proto__); //Number.prototype.__proto__: Object { … } 空对象 console.log("Boolean.prototype.__proto__:",Boolean.prototype.__proto__); //Boolean.prototype.__proto__: Object { … } 空对象 console.log("self defined function"); function test(){} console.log("test:",test);//test: function test() 自定义函数 console.log("test.prototype:",test.prototype);//test.prototype: Object { … } 空对象 console.log("test.prototype.constructor:",test.prototype.constructor); //test.prototype.constructor: function test() 自定义函数 console.log("test.__proto__:",test.__proto__);//test.__proto__: function () 空函数 console.log("test.prototype.__proto__:",test.prototype.__proto__); //test.prototype.__proto__: Object { … } 空对象
标签:alt 分享 height class 找对象 其他属性 自定义 构造 prot
原文地址:https://www.cnblogs.com/go4it/p/9906306.html