#|Javascript之原型与原型链


原型与原型链

  • 1. 原型(prototype)
      • 1.1 每个函数都有一个prototype属性,且默认指向一个空的Object对象
      • 1.2 原型对象中有一个属性constructor,它指向函数对象
      • 1.3 给原型对象添加属性
  • 2. 显式原型与隐式原型
  • 3.原型链
      • 3.1 原型链图解
        • 图解一:以Fn与Obecjt为例
        • 图解二:以两种创建对象的方式为例
        • 图解三:以function Foo(){}为例
      • 3.2 原型链补充( 重要 )
      • 3.3原型链的属性问题
  • 4. 探索instanceof底层原理
    • 4.1 案例一

1. 原型(prototype)
原型 - 锐客网> // 输出Date原型中的属性及方法以及Date原型的类型 console.log(Date.prototype, typeof Date.prototype)// 定义一个函数Fn function Fn(){} // 输出Fn原型中的属性及方法以及Fn原型的类型 console.log(Fn.prototype, typeof Fn.prototype) // 查看原型中对象的constructor属性是否指向原对象 console.log(Date.prototype.constructor === Date) console.log(Fn.prototype.constructor === Fn)// 给原型对象添加属性 Fn.prototype.test = function(){ console.log("test....") } // 声明一个实例对象 var f1 = new Fn(); // 调用原型中的方法 f1.test()

1.1 每个函数都有一个prototype属性,且默认指向一个空的Object对象
console.log(Date.prototype, typeof Date.prototype)

输出Date原型中的属性及方法以及Date原型的类型
#|Javascript之原型与原型链
文章图片

function fn(){} console.log(fn.prototype, typeof fn.prototype)

自定义fn函数,输出fn函数的原型,默认为空对象(并没有多余的属性和方法),原型类型为Object
#|Javascript之原型与原型链
文章图片

1.2 原型对象中有一个属性constructor,它指向函数对象
console.log(Date.prototype.constructor === Date) // true console.log(fn.prototype.constructor === fn)// true

定义一个Type函数 function Type(){ }
其内部有prototype属性,此属性指向一个对象,对象中有constructor属性,指向原来的Type函数
#|Javascript之原型与原型链
文章图片

1.3 给原型对象添加属性
function Fn(){} // 给原型对象添加属性(一般是方法)可供实例对象使用 Fn.prototype.test = function(){ console.log("test....") } // 声明一个实例对象 var f1 = new Fn(); // 调用原型中的方法 f1.test()

2. 显式原型与隐式原型
显式原型与隐式原型 - 锐客网> // 创建一个构造函数 function Fun(){ // 内部隐含语句:this.prototype = {} }// 1.每个函数function都有一个prototype属性,即显式原型属性,默认指向空的Obejct对象 console.log(Fun.prototype); // 2.每个实例对象都有一个__proto__ , 可称为隐式原型属性, // 默认指向和函数相同指向的那个空的Obejct对象 var fun = new Fun(); // 内部隐含语句 this.__ptoto__ = Fun.prototype console.log(fun.__proto__); // 3.对象的隐式原型的值为其对应构造函数的显式原型的值 console.log(Fun.prototype === fun.__proto__); // true

#|Javascript之原型与原型链
文章图片

#|Javascript之原型与原型链
文章图片

3.原型链
原型链 - 锐客网> console.log(Object.prototype) function Fn(){ this.test1 = function(){ console.log('test1....'); } }Fn.prototype.test2 = function(){ console.log("test2....."); }var f1 = new Fn(); f1.test1(); f1.test2(); f1.test3();

3.1 原型链图解
图解一:以Fn与Obecjt为例
  1. 在开始时,浏览器会在内存中创建Obejct函数对象,假设为0x456,函数对象存在prototype属性,Object的prototype属性会指向其原型对象,假设其原型对象地址值为0x345。
  2. 开发人员创建Fn函数时,会在栈中存储Fn的变量,其保存Fn函数对象的地址,假设为0x123,同时其函数对象内部的prototype属性会指向一个空的Object对象,假设为0x234。
  3. Fn.prototype.test2表示在Fn内部的prototype指向的空对象中会创建一个test2函数对象
  4. 当执行var fn = new Fn()时会在栈中生成一个fn变量,保存Fn实例对象的地址,假设为0x567
    #|Javascript之原型与原型链
    文章图片
图解二:以两种创建对象的方式为例
  1. 当使用var o1 = new Object()方式创建一个对象时,o1为实例对象,按照原则,实例对象内部有__proto__属性,其指向创建自己的函数对象的原型对象,即为Object()的原型对象,原型对象中存在constructor属性,指向函数对象本身,因此在函数对象和其原型对象之间会形成一个环,即表现为互相引用,互相指向。
  2. 使用var o2 = {}方式创建对象与上述方式相同
    #|Javascript之原型与原型链
    文章图片
图解三:以function Foo(){}为例
  1. 执行function Foo(){}时,会在内存中生成Foo函数对象以及其指向的原型对象,函数对象中存在prototype属性,其保存的地址值指向其原型对象(即为下图中线1所表示),原型对象中存在constructor属性,其保存的地址值指向其对应得函数对象(即为下图中线2所表示)。
  2. 因为开发人员定义的任何函数都是通过new Function()创建的,例如创建方式为var Foo = new Functon(),因此创建得到的函数也属于Function的实例对象,因此创建的函数也具备__proto__属性,其指向创建自己函数对象的原型对象(即为下图中线3所表示)。
  3. 由下图可知Function本身具备__proto__属性,此属性为实例对象所具备的,因此可知Function也为某个函数的实例对象,通过下图中的线4可知,Function的__proto__指向自身的prototype,因此可知,Function是通过自身创建的,即为Function = new Function()。从Function()作为函数对象的角度来看,函数对象具备prototype,其指向自身的原型对象,即为下图中线5所表示,而原型对象也会又constructor属性,指向自身的函数对象,即下图中线6所表示的。
  4. Object()也是一个函数对象,因此它也是通过Function()所创建的,因此Object()函数对象也是实例对象,其内部也存在__proto__指向创建自身的函数对象的原型,即为Function()函数对象的原型,即下图中线9所表示的。
    #|Javascript之原型与原型链
    文章图片
3.2 原型链补充( 重要 )
原型链补充 - 锐客网 > function Fn(){} // 1.函数的显式原型指向的对象默认是空Object对象,但对于Object函数来说并不满足此条件 console.log(Fn.prototype instanceof Object)// true console.log(Object.prototype instanceof Object)// false // Function函数对象的原型也是Object的实例对象 console.log(Function.prototype instanceof Object)// false// 2.所有的函数都是Function的实例,包括function自身 console.log(Function.__proto__ === Function.prototype)// true// 3.Object的原型对象是原型链的尽头 console.log(Object.prototype.__proto__)// null

3.3原型链的属性问题
原型链_属性问题 - 锐客网="text/javascript"> function Person(name, age) { this.name = name; this.age = age; } Person.prototype.setName = function (name) { this.name = name; } Person.prototype.sex = '男'; var p1 = new Person('Tom', 12) p1.setName('Jack') console.log(p1.name, p1.age, p1.sex) p1.sex = '女' console.log(p1.name, p1.age, p1.sex)var p2 = new Person('Bob', 23) console.log(p2.name, p2.age, p2.sex)

#|Javascript之原型与原型链
文章图片

4. 探索instanceof底层原理 4.1 案例一
05_探索instanceof - 锐客网="text/javascript"> //案例1 function Foo() {} var f1 = new Foo(); console.log(f1 instanceof Foo); console.log(f1 instanceof Object); //案例2 console.log(Object instanceof Function) console.log(Object instanceof Object) console.log(Function instanceof Object) console.log(Function instanceof Function) function Foo() {} console.log(Object instanceofFoo);

1. 判断f1是否是Foo的实例,对于f1来说,沿着__proto__向上第一个节点为Foo.prototype, Foo查看prototype的指向,因此两条线路相交于Foo.prototype,则是Foo的实例 2. 判断f1是否是Object的实例, 对于f1来说,沿着__proto__向上第一个节点为Foo.prototype, Object的prototype指向Object.prototype, 各向上走一步并没有相交,f1可沿着__proto__继续向上走,第二个节点指向Object.prototype , 两则在此处相交,因此是Object的实例。

【#|Javascript之原型与原型链】#|Javascript之原型与原型链
文章图片

    推荐阅读