浅谈JS中原型链和继承

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36091581/article/details/79128047

浅谈JS中原型链和继承

 最近有很多面试官提到JS中原型链和继承的关系,面试者答得云里雾里有点含糊。那我们来好好理一下什么是原型链,什么是原型链继承。

原型链是什么?所谓的原型链是一个有限的实例对象和原型之间组成的有限链,就是用来实现共享属性和继承的。简单的一句话就是构造函数一层一层往父级找直到找到null为止的一条链。
其实,所有的函数都是 Function 的实例。在构造函数上都有一个原型属性 prototype,该属性也是一个对象;那么在原型对象上有一个 constructor 属性,该属性指向的就是构造函数;而每个实例对象上有一个 proto 属性,该属性也指向原型对象,并且该属性不是标准属性,不可以用在编程中,该属性用于浏览器内部使用。
我们举个简单的例子来理解一下:

  var obj = new Object();
//  对象是有原型对象的
// 原型对象也有原型对象 
   obj._proto_._proto_._proto_
// 原型对象也有原型对象,对象的原型对象一直往上找,会找到一个null
 // 原型链示例
   var arr = [];
   arr -> Array.prototype ->Object.prototype -> null
   var o = new Object();
   o -> Object.prototype -> null;

构造函数、原型和实例之间的关系
①+Object
这里写图片描述
上图可见:foo是一个构造函数(每个构造函数上都有一个原型属性 prototype),它有两个实例对象,分别是foo2和foo1,在每个实例对象上都有_proto_属性,info的是实例对象上自定义的属性。foo的原型对象是foo.prototype,它有一个constructor属性(constructor指向的是它的构造函数)。以此类推可知object的原型对象和构造函数。
②+Function+Object+Array

这里写图片描述

再举个例子:

function Person(){  
  this.name="bob" //这是一个实例属性  
}  
Person.prototype.eat=function(){ //给对象的原型对象添加一个eat的方法,接下来,new的实例会共享这个方法  
  return "food";  
}  
var p1=new Person();  //这里究竟发生生了什么?  
p1.eat()//->food  
var p2=new Person();  
p2.eat()//->food,所以只要是Person的对象,他们都会共享原型对象的方法,当然,p1.name也会共享Person的实例属性,因为p1是Person的一个实例    
function Person(){  
  this.name="bob" ;  
}  
Person.prototype.eat=function(){  
  return "food";  
}  
function Student(){}  

Student.prototype=new Person();  
Student.prototype={  
  run:function(){  
    return "run";  
  }  
};  
var one=new Student();  
console.log(one.eat());//Uncaught TypeError: undefined is not a function   

在上面的代码中,把Person的实例赋给Student的原型,接下来又把原型改写成另一个对象字面量,现在原型包含的是Object实例,不再是Person实例,因此原型链已经被切断了,也就是说Student和Person没关系了。

继承

1.原型继承

function Animal(name){
       this.name = name;
   }
   function Tiger(color){
       this.color = color;
   }
//   var tiger = new Tiger('yellow');
//   console.log(tiger.color);
//   console.log(tiger.name);  //undefined
//      Tiger.prototype = new Animal('老虎');   //一种方式
   Object.prototype.name = '大老虎';   //第二种方式
        var tiger = new Tiger('yellow');
        console.log(tiger.color);  // log 'yellow'
        console.log(tiger.name);  // log '大老虎'

2.拷贝继承

function Animal(name){
    this.name = name;
}
function Mouse(nickname){
    Animal.call(this,'老鼠');
    this.nickname = nickname;
}
var m = new Mouse('杰瑞');
console.log(m.name); // log '老鼠'
console.log(m.nickname);// log '杰瑞'

总结

1、原型链

1)构造函数、原型和实例的关系

    ①构造函数都有一个属性prototype,这个属性是一个对象(Object的实例)
    ②每个原型对象prototype里面有一个constructor属性,该属性指向原型对象所属的构造函数
    ③实例对象都有一个_proto_属性,该属性也指向构造函数的原型对象,它是一个非标准属性,不可以用于编程,它是用于浏览器自己使用的
2)prototype与_proto_的关系


    ①prototype是构造函数的属性

    ②_proto_是实例对象的属性

                ——这两者都指向同一个对象

【总结】i)函数也是对象,对象不一定是函数;

        ii)对象的本质:无序的键值对集合;键值对当中的值可以是任意数据类型的值

        iii)对象就是一个容器,这个容器当中放的是(属性和方法)

3)属性搜索

  ①在访问对象的某个成员的时候会先在对象中找是否存在

  ②如果当前对象中没有就在构造函数的原型对象中找

  ③如果原型对象中没有找到就到原型对象的原型上找

  ④知道Object的原型对象的原型是null为止

2、Function

——所有函数都是Function的实例

①本地对象:独立于宿主环境(浏览器)的对象——包括Object、Array、Date、RegExp、Function、Error、Number、String、Boolean

②内置对象——包括Math、Global(window,在js中就是全局变量),使用的时候不需要new

③宿主对象——包括自定义对象、DOM、BOM

猜你喜欢

转载自blog.csdn.net/qq_36091581/article/details/79128047