前端面试题之原型链常见面试题总结

1.如何准确判断一个变量是数组类型。

使用instanceof进行判断,typeof是无法判断数组的。在ES6中新增了Array.isArray方法进行判断。

2.写一个原型链继承的例子

  //动物的构造函数,有一个方法eat
  function Animal() {
    this.eat = function () {
      console.log('animal eat');
    }
  }
  //狗的构造函数,有一个方法bark
  function Dog() {
    this.bark = function () {
      console.log('dog bark');
    }
  }
  //将Animal的实例赋值给Dog的原型对象
  Dog.prototype = new Animal()
  //new了一个Dog的实例对象,原型对象有eat方法,原型链上有bark方法
  var tudog = new Dog()
  console.log(tudog); //自身拥有bark方法,原型上拥有eat方法

在上面这个例子中,Animal是一个构造函数,Dog也是一个构造函数,我们将Dog的原型对象变成了Animal的实例对象当我们new一个Dog的时候,先从本身继承了bark方法,同时继承了原型链Animal上的eat方法,当我们调用eat方法的时候,就会打印animal eat,是因为当在当前对象中的属性没有找到此方法,便会沿着原型链进行寻找知道Object.prototype这个大boss的原型对象上才终止,因为它的原型对象是null。

3.请介绍一下什么是原型。

原型是一个函数,其中的prototype是原型对象,这是开始就有的。在原型对象中其中定义了一些公用的属性和方法
重点:
1.每一个函数对象都有一个prototype属性,但是普通对象是没有的。
2.prototype原型对象中有一个constructor构造函数,指向这个函数
3.每个对象都有一个__proto__的内部属性,指向所对应的构造函数的原型对象,原型链是基于__proto__的。
原型的主要作用就是实现继承与扩展对象。

4.请介绍一下原型链。

每一个函数都有一个prototype属性,成为原型,而原型的值也是一个对象,因此它也有自己的原型,这样就串起了一条原型链。原型链的链头是Object,他的prototype比较特殊,值为null。
每个函数都有一个prototype属性,它是一个引用变量,默认指向一个空的object对象。当调用一个对象的函数或者是属性的时候,如果在当前对象里面找不到,那么就会在原型对象上逐层寻找。
在javascript中,所有的对象都有一个__proto__的属性,它指向了当前对象的原型(prototype)。比如Animal是一个构造函数,它的本质就是一个函数,在js中函数是一等对象。
可以说,原型链是原型对象创建过程中的历史记录。
每一个对象都会在内部生成一个proto属性,当我们访问一个对象属性的时候,如果在这个对象中不存在这个属性,那么就会在它的proto属性指向的对象中去寻找。一层一层找下去,当最后找到Object.prototype的时候,这条原型链就到头了。(proto最终指向obj)
我们来看一个例子巩固一下刚学的知识:

  var Person = function (name) {
    this.name = name; //给Person对象增加了一个name属性,值为传入的值。
  }
  Person.prototype.sayHi = function () {  //Person的原型对象增加了sayHi方法
    console.log("Hello! I am " + this.name + ".");
  }

  var joe = new Person("joe");  
  //new了一个实例会实现以下几步
  //1.创建一个空对象obj
  //2.设置这个空对象的__proto__的属性指向构造函数的prototype
  //3.让构造函数的this指向这个空对象,然后执行构造函数里面的代码
  //4.如果函数没有return语句,或是return基础类型,返回生成的对象
  //5.如果函数return了一个引用类型的数据,则最终返回这个引用类型
  var john = new Person("john");

  joe.sayHi(); //Hello! I am joe.
  john.sayHi(); //Hello! I am john.

上面的代码中,首先声明了一个Person构造函数,其中的this.name到了每一个新的实例中都会执行一遍,相当于Object.name = name,第二步我们给它的原型对象上添加了一个sayHi的方法,在new实例时,将会有_proto_指向此对象,同时也继承了此方法。new实例后,首先生成一个空对象,接下来将对象的_proto_的属性指向了原型对象,接着将构造函数中的代码执行了一遍,因此在新的实例中,拥有了name这个属性,同时也继承了原构造函数prototype的方法,因为没有return一个引用类型,因此new实例获得的是我们生成的对象。
从上面的描述中我们总结如下:原型定义了一些公用的属性和方法,利用原型新构建出来的对象实例会共享原型的所有属性和方法。
原型链:原型链是原型对象创建过程中的历史记录。

5.为什么方法放在prototype原型对象中而不放在构造函数的属性中

放在Prototype中只需要在构造函数中实现一次加载,在new的实例中只需要_proto_指向此对象即可通过原型链使用此方法,而如果放在构造函数的属性中,每次new实例都需要调用一次,比较浪费性能。

6.说一下instanceof的原理

instanceof判断实例对象的_proto_属性,和构造函数的prototype属性,是不是同一个引用,所以只要是在原型链上的构造函数都是new实例的构造函数,都返回true,使用_proto_.constructor === M 进行判断实例是不是构造函数的实例,比Instanceof更严谨。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值