原型实例化原型链

Posted wssjzw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原型实例化原型链相关的知识,希望对你有一定的参考价值。

在使用面对对象编程时,对象间的继承关系自然少不了!而原型正是实现javascript继承的很重要的一种方法!JS的原型链只针对 对象,仅对象才具有的!!!

function person(name, age) { 
  this.name = name; 
  this.age = age; 
} 
person.prototype.getInfo = function() { 
  alert("My name is "+this.name+", and I have "+this.age+" years old"); 
} 
var zhangchen = new person("zhangchen", 23); 
zhangchen.getInfo(); //output My name is zhangchen, and I have 23 years old; 

  从运行的结果我们可以看出,通过关键字new创建的zhangchen这个对象继承了person中通过原型定义的getInfo()方法.

下面我们具体来看新建的zhangchen这个对象是如何继承person对象的属性和方法的

  原型在使用javascript的面对对象编程中,原型对象是个核心概念。在javascript中对象是作为现有实例(即原型)对象的副本而创建的,该名称就来自于这一概念。此原型对象的任何属性和方法都将显示为 从原型的构造函数创建的 对象的 属性和方法。当创建zhangchen对象时:

var zhangchen = new company("zhangchen", 23); 

可以说,这些对象从其原型继承了属性和方法。

 

  zhangchen所引用的对象将从它的原型继承属性和方法,对象zhangchen是由new方法  通过 company("zhangchen",23)函数构建得来的

 

在javascript中,每个函数都有名为prototype的属性,用于引用该函数的原型对象。该函数对应的原型对象又有名为constructor的属性,它反过来引用函数本身。

这是一种循环引用,如下图

技术分享图片

  现在,通过new运算符将函数(person)构建成对象时,所获得的对象将继承person.protype的属性。在上图,可以看到person.prototype对象有一个回指person函数的构造函数属性。这样,每个person对象(从person.prototype继承而来)都有一个回指person函数的构造函数属性。

 

person.prototype 和 person实例中还可以调用其他方法,比如toString、toLocaleString和valueOf,但它们都不来自person.prototype。而是来自于javascript中的Object.prototype,它是所有原型的最终基础原型。( Object.prototype 的原型是 null )

原型链:每个JavaScript对象都继承一个原型链,而所有原型链都终止于Object.prototype。注意,这种继承是活动对象之间的继承。它不同于继承的常见概念,后者是指在声明类时类之间的发生的继承。因此javaScript继承动态性更强。它使用简单算法实现这一点,如下所示:当你尝试访问对象的属性、方法时,javaScript将检查该属性、方法是否是在该对象中定义的。如果不是,这检查对象的原型。如果还不是,则检查对象的原型的原型,如此直到Object.prototype。

 

以上看的不是很明白 讲的这个对象那个对象傻傻分不清 没关系 看看下面这篇:

 

一、初始原型

  在javaScript中,原型也是一个对象,通过原型可以实现对象属性继承(上一层的属性,下一层属性可以调用),javaScript的对象都包含了一个“[[Prototype]]”作为对象的内部属性,这个属性对应的就是该对象的原型  “[[Prototype]]"作为对象的内部属性,是不能被直接访问的。所以为了方便查看一个对象的原型,Firefox和Chrome中提供了_proto_这个非标准属性(不是所有浏览器都支持)的访问器(ECMA引入标准对象原型访问器“Object.getPrototype(object)”)。在javaScript的原型对象中,还包含一个“constructor”属性,这个属性对应创建所有指向该原型的实例的构造函数---这句话这麽拗口,那到底是什么意思呢!!?  很简单 constructor属性   原型  能够通过new方法得到该原型的函数  这句话涉及到的三个知识点就是指 原型 能够通过 constructor属性 得到 所有 能够通过new方法得到该原型的函数③ ,另外补充的一点当函数通过new方法创建原型对象时,如果出错,在“错误的”(不是我们想要的)原型中 constructor属性 会指出错误原因!

var person = function(name,age){
  this.name = name;
  this.age = age;
}
var p1 = new person();  //不会报错 但所有属性都是undefined 缺少参数!                
function a(name,age){alert(1);}
a(); //无参数 可以调用 不会报错(函数体内不涉及到参数)
//constructor 当你实例化某个对象时,必须要给出指定的参数 又叫构造方法

  那么有人就有问题了,new方法是什么呢?不急,向下看!

 

二、规则

在javaScript中,每个函数 都有一个prototype属性,当一个函数被用作构造函数来创建实例时,这个函数的prototype属性值会被作为原型赋值给所有对象实例(也就是设置 实例的‘_proto_’属性),也就是说,所有实例的原型引用的是函数的prototype属性。(‘只有函数对象才会有这个属性!’

 

 New方法的过程分为三步(new方法又称为实例化)

var p = new Person(张三,20);

   1. var p={};初始化一个对象p。

   2. p._proto_=Person.prototype;将对象p的_proto_属性设置为Person.prototype

   3. Person.call(p,"张三",20);调用构造函数Person来初始化p。关于call、apply使用

 

三、初识object

  Object对象本身是一个函数对象。(CODE TEST)既然是Object函数,就肯定会有Prototype属性,所以可以看到"Object.prototype"的值就是"Object{}"这个对象。反过来,当访问"Object.prototype"对象的"constructor"(构造器)这个属性的时候,就得到了Object函数。

  另外,当通过"Object.prototype._proto_"获取Object原型的原型的时候,将会得到"null",也就是说"Object{}"原型对象就是原型链的终点了。这里会有人喜欢出面试题:原型链的根只能为Object!× 还能为null

 

四、初识Function

对于所有的对象,都有_proto_属性,这个属性对应该对象的原型。

对于函数对象,除了_proto_属性之外,还有Prototype属性,当一个函数被用作构造函数来创建实例时,该函数的prototype属性值将被作为原型赋值给所有对象实例(也就是设置实例的_proto_属性)技术分享图片

 

原型链

因为每个对象和原型都有原型,对象的原型指向原型对象,而父的原型又指向父的父,这种原型层层连接起来的就构成了原型链。

 

一、属性查找

  当查找一个对象的属性时,javaScript会向上遍历原型链,直到找到给定名称的属性为止,到查找到达原型链的顶部(也就是Object.prototype),如果仍然没有找到指定的属性,就会返回undefined。

function Person(name, age){ 
    this.name = name; 
    this.age = age; 
  } 
Person.prototype.MaxNumber = 9999;
Person.__proto__.MinNumber = -9999;
var will = new Person("Will", 28); 
console.log(will.MaxNumber); // 9999 
console.log(will.MinNumber); // undefined 

  在这个例子中分别给”Person.prototype “和” Person._proto_”这两个原型对象添加了”MaxNumber “和”MinNumber”属性,这里就需要弄清”prototype”和”proto”的区别了:

  "Person.prototype"对应的就是Person构造出来所有实例的原型,也就是说"Person.prototype"属于这些实例化原型链的一部份,所以当这些实例进行属性查找时候,就会引用到"Person.prototype"中的属性。

   对象创建方式影响原型链

var July = {
   name: "张三",
   age: 28,
   getInfo: function(){
     console.log(this.name + " is " + this.age + " years old");
   }
 }
console.log(July.getInfo()); 

  当使用这种方式创建一个对象的时候,原型链就变成下图了,July对象的原型是“Object.prototype”也就是说对象的构建方式会影响原型链的形式

 

 

技术分享图片

总结:

  1、在javascript中,每一个函数实际上都是一个函数对象

  2、原型链的根原型为Object,即所有原型的最上层原型都为Object

  3、所有的对象都有_proto_属性,该属性对应该对象的原型

  4、所有的函数对象都有prototype属性,该属性的值会被赋值给该函数创建的对象的_proto_属性。

  5、注意:函数对象没有_proto_属性,对象没有prototype属性

  6、所有的原型对象都有constructor属性,该属性对应创建所有指向该原型的实例化的构造函数

  7、函数对象和原型对象通过prototype和constructor属性进行相互关联。

 

文章来自 “编程的人”,

 

以上是关于原型实例化原型链的主要内容,如果未能解决你的问题,请参考以下文章

面向对象与原型链

原型链、constructor和prototype图文详解

初始原型链

JS高级---原型和原型链

JavaScript使用原型链实现继承

原型和原型链的扯淡