前端面试之创建对象与原型链

适逢传说中的金三银四,最近在阅读掘金和GitHub的时候看多多次各路大牛出的关于原型链的题目,如果没有深刻的理解,过一段时间就会又不知所云。
我也是在做过此类题目一段时间后又模糊了其含义。因此特意在笔记本上画了原型对象与原型链的示意图来帮助理解。提到这,我个人还是比较喜欢使用纸质笔记本记录知识,平时看到一个小的知识点就可以随手记录下来。

本文涉及点:

  • 1.面向对象三大特性
  • 2.继承
  • 3.构造函数
  • 4.原型链
  • 5.认识和创建对象的几种方法
  • 6.new运算符
  • 7.instanceof及其原理

1.面相对象的三大特性

  • 封装
  • 继承
  • 多态

2.当谈到继承时,JavaScript 只有一种结构:对象。

每个实例对象(object )都有一个私有属性(称之为__proto__)指向它的原型对象(prototype)。该原型对象也有一个自己的原型对象(proto) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

3.原型链

几乎所有 JavaScript 中的对象都是位于原型链顶端的Object的实例。

原型链的基本原理:任何一个实例,通过原型链,找到它上面的原型,该原型对象中的方法和属性,可以被所有的原型实例共享。

这里先说下构造函数:
1、构造函数通过 new 生成实例

2、构造函数也是函数,构造函数的prototype指向原型。(所有的函数有prototype属性,但实例没有 prototype属性)

3、原型对象中有 constructor,指向该原型的构造函数。
如下图:
前端面试之创建对象与原型链
这样梳理一遍可以加深理解。

4.认识与创建对象的几种方法

在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:
普通对象 Object 和 函数对象 Function
一般而言,通过 new Function 产生的对象是函数对象,其他对象都是普通对象。

1.创建函数
如下代码:

//函数声明
function f1() {
    console.log("函数的声明")
}
//函数表达式
var f2 = function () {
    console.log("f2实际上是一个匿名函数,把这个匿名函数赋值给了f2")
};
//直接new Function() 创建函数
var f3 = new Function('x',  'console.log(x)');

console.log(
    typeof f1,//function 
    typeof f2,//function 
    typeof f3//function 
);

2.创建对象 的方法
创建对象代码:

var o1 = {};//字面量
var o2 = new Object();//使用new表达式
var o3 = new f1();
 
console.log(
    typeof o1,//object
    typeof o2,//object
    typeof o3//object
);
  • 方式一:对象字面量

    var obj1 = {name: 'xiaohua'};//字面量的方式
    var obj2 = new Object(name: `xiaohua`); //内置对象(内置的构造函数)的方式
    

    上面的两种写法,效果是一样的。因为,第一种写法,obj1会指向Object。

  • 方式二:通过构造函数,使用new表达式

    var f1= function (name) {
      this.name = name;
    }
    var obj3 = new f1('xiaohua');
    
  • 方式三:Object.create
    Object.create方法创建的对象,是用原型链连接的。

    var f2 = {name:'xiaohua'};
    var obj3 = Object.create(f2);  
    

    这种方法很少有人可以说出来,这里obj3是实例,f2是obj3的原型,name是f2原型里的属性。构造函数是Objecet 。
    前端面试之创建对象与原型链

5.new运算符

当new一个实例new f1(‘xiaohua’)的时候,发生了什么?

(1)创建一个新的空对象实例。

(2)将此空对象的隐式原型指向其构造函数的显示原型。

(3)执行构造函数(传入相应的参数,如果没有参数就不用传),同时 this 指向这个新实例。

(4)如果返回值是一个新对象,那么直接返回该对象;如果无返回值或者返回一个非对象值,那么就将步骤(1)创建的对象返回。

6.instanceof

1.定义

instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置。
(来自MDN)
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
(来自MDN)

instanceof的作用:用于判断实例属于哪个构造函数。

instanceof的原理:判断实例对象的__proto__属性,和构造函数的prototype属性,是否为同一个引用(是否指向同一个地址)。

2.语法

object instanceof constructor

参数:

object:要检测的对象。

constructor:某个构造函数。

特别说明:

注意1:虽然说,实例是由构造函数 new 出来的,但是实例的__proto__属性引用的是构造函数的prototype。也就是说,实例的__proto__属性与构造函数本身无关。

注意2:在原型链上,原型的上面可能还会有原型,以此类推往上走,继续找__proto__属性。这条链上如果能找到, instanceof 的返回结果也是 true。

【每天学习一个点,慢慢的,慢慢的,慢慢的!】