好久没写文章了,最近在看一些js基础相关的知识,无论是在工作中还是面试时,前端都避不开一个知识,那就是对原型知识的理解。好一些的公司面试官必回问一个问题—“对js原型的理解”。那么今天我就简单的谈谈这块知识,不跟你多bb,下面是正文了。

    下面先来了解几个规则:
    **

    • 所有的引用类型,都具有对象特性,即可自由扩展属性(除了“null”以外)
    • 所有的引用类型,都有一个隐式原型proto属性,属性值是一个普通的对象
    • 所有的引用类型,隐式原型proto属性值指向它的构造函数的显式原型“prototype”属性值
    • 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型proto(也就是它的构造函数的显式原型prototype)中寻找。

    那么我们来一一的验证上面几个原则,就会慢慢的理解原型和原型链。

    1、所有的引用类型,都具有对象特性,即可自由扩展属性(除了“null”以外)。

    1. var obj = {};
    2. var arr = [];
    3. var fn = function() {}
    4. obj.a = 1;
    5. arr.a = 2
    6. fn.a = 3

    这个规则应该比较好理解,额外介绍一个小知识点,var obj ={}; 相当于 var obj = new Object(); 不过在正常的工作业务中,不会去这么定义一个对象,因为不仅麻烦,可读性也会变差。

    2、所有的引用类型,都有一个隐式原型proto属性,属性值是一个普通的对象。
    **

    1. var obj = {};
    2. var arr = [];
    3. function fn() {}
    4. console.log(obj.__proto__);
    5. console.log(arr.__proto__);
    6. console.log(fn.__proto__);

    image.png

    3、所有函数都有一个显式原型 prototype。
    **
    image.png

    4、当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的proto(也就是它的构造函数的显式原型prototype)中寻找。
    **

    1. var obj = {a:1};
    2. obj.toString(); // [object, object]

    obj 本身是没有toString方法属性的,之所以能获取到这个方法,其实就是遵循了第四条规则,从他的构造函数Object的prototype中去拿到了这个方法。

    再看一个例子:
    **

    1. function Person(name) {
    2. this.name = name;
    3. return this; // 其实这行可以不写,默认不认返回this对象
    4. }
    5. var nick = new Person("nick");
    6. nick.toString(); // [object, object]

    按理说,nick 是构造函数Person生成的实例,而它的 prototype 并没有 toString 方法,那为什么 nick 对象能获取到 toString 方法呢?其实这就涉及到原型链了,nick 先去找自身有无 toString 方法属性,找不到那就往上走,找构造函数的 prototype,还是没找到,那么就继续往上,构造函数的 prototype 其实也就是一个对象(如下图所示),那么对象的构造函数就是 Object,所以就找到了 Object.prototype 下的 toString 方法。

    image.png

    用一张图片来解释一下上面的流程:
    **
    image.png

    最后一个 null,设计上是为了避免死循环而设置的, Object 的隐式原型指向 null。

    既然说到了原型,那就说说判断一个引用类型的变量。如下代码:

    1. function Foo(name) {
    2. this.name = name;
    3. }
    4. var f = new Foo('nick')
    5. f instanceof Foo // true
    6. f instanceof Object // true

    instanceof 是通过原型去进行比较对象是否属于当前比较的构造函数, f instanceof Foo 的判断逻辑: f 的隐式原型 proto 一层一层往上,能否对应到 Foo.prototype 同理 f instanceof Object 也是为 true ,因为往上找,也能找到 Object.prototype

    写得不好请见谅。