浅谈对JavaScript原型的理解

说到JavaScript原型,我硬是花了几个月才把这个概念吃透。

原型与对象的关系就好比是印章和印章印出的印一样,我们必须要聊到的两个属性是__proto__和prototype。

   Object.prototype.Show = function() {
            console.log("Hello World!");
        }

        var obj = {
            "eat": function() {
                console.log("ok");
            }
        }

        obj.Show();
	console.log(obj.prototype);//undefined
        console.log(obj.__proto__ === Object.prototype);

首先说说对象字面量,每一个对象都有一个__proto__,这个属性关联着Object.prototype的,于是如果我们想让所有的对象都有特定的属性或者方法,我们就可以在Object.prototype上面挂接相应的属性即可,并且,在以上代码中,我们可以看出,非函数对象是不具有prototype这个属性的。

然后,说说prototype,这个是函数对象特有的属性(JavaScript中,万物皆对象)。

我们以构造函数的形式创建对象,一般都是这样的套路:

  function ObjCreator() {

            this.tell = function() {
                console.log("Hello World!");
            }

        }
        var obj = new ObjCreator();
        obj.tell();
        console.log(obj.__proto__===ObjCreator.prototype);//true
我们惊人的发现obj.__proto__===ObjCreator.prototype,这样,构造函数创建的对象给到对象变量上,于是我们的对象获得构造函数及其原型对象上所定义的所有属性,再进一步,我们在输出 console.log(ObjCreator.prototype.__proto__ === Object.prototype);,这个居然是true,构造函数的原型对象关联着Object的原型对象,那么,JavaScript的原型链,我们已经搞清楚一半了。在这里,如果我们想要继承,就可以直接修改原型链即可:

  function ObjCreator() {

            this.tell = function() {
                console.log("Hello World!");
            }

        }


        function Child(){


        };


        Child.prototype=new ObjCreator();

这样,以后Child构造函数创造的对象,将会拥有所有ObjCreator实例的方法和属性。

继续扯,

  console.log(Child.__proto__ === Function.prototype);这个也是true,说明构造函数的__proto__关联着函数原型对象,那么如果我们在函数原型对象上添加方法,那么构造函数就会拥有这些方法,那么,如果这个构造函数是系统定义的呢?那么不就意味着我们可以向JavaScript内置对象中扩展新的功能了吗?于是,便有了这样的代码

 Function.prototype.method = function(name, fn) {
            if (!this.prototype[name]) {
                this.prototype[name] = fn;//保证每一个对象都要有相应的方法。
                console.log(this);
            }

        }
	//挂接方法
        Number.method("ToInt", function() {

            return this > 0 ? Math.floor(this) : Math.ceiling(this);

        });

        console.log((10 / 3).ToInt());//3

最后,我们再打印一下Function.prototype.__proto__,它关联着Object.prototype。

于是,所有的谜题都解开了,对象通过__proto__关联着它的原型对象(继续关联它的原型对象),实现复杂的JavaScript原型链,构造函数通过"函数名.prototype"在其中插了一脚,使得我们理解原型变得困难,prototype只在函数对象中存在,并且,当我们使用构造函数new的时候,相当于新建一个对象,然后把构造函数中属性和方法以及原型对象所有的属性和方法复制到这个对象里面去,返回给我们(假如我们不使用new的话,写东西就给到了window对象上了)。

你可能感兴趣的:(Web前端)