0
点赞
收藏
分享

微信扫一扫

使用JavaScript的原型

在 javascript 中,函数可以有属性。每个函数都有一个特殊的属性叫作原型(prototype)。

function doSomething(){}
console.log( doSomething.prototype );

运行这段代码之后,控制台上面应该出现了像这样的一个对象。

{
    constructor: ƒ doSomething(),
    __proto__: {
        constructor: ƒ Object(),
        hasOwnProperty: ƒ hasOwnProperty(),
        isPrototypeOf: ƒ isPrototypeOf(),
        propertyIsEnumerable: ƒ propertyIsEnumerable(),
        toLocaleString: ƒ toLocaleString(),
        toString: ƒ toString(),
        valueOf: ƒ valueOf()
    }
}

现在,我们可以添加一些属性到 doSomething 的原型上面,如下所示。

function doSomething(){}
doSomething.prototype.foo = "bar";
console.log( doSomething.prototype );

结果:

{
    foo: "bar",
    constructor: ƒ doSomething(),
    __proto__: {
        constructor: ƒ Object(),
        hasOwnProperty: ƒ hasOwnProperty(),
        isPrototypeOf: ƒ isPrototypeOf(),
        propertyIsEnumerable: ƒ propertyIsEnumerable(),
        toLocaleString: ƒ toLocaleString(),
        toString: ƒ toString(),
        valueOf: ƒ valueOf()
    }
}

然后,我们可以使用 new 运算符来在现在的这个原型基础之上,创建一个 doSomething 的实例。正确使用 new 运算符的方法就是在正常调用函数时,在函数名的前面加上一个 new 前缀。通过这种方法,在调用函数前加一个 new ,它就会返回一个这个函数的实例化对象。然后,就可以在这个对象上面添加一些属性。看:

function doSomething(){}
doSomething.prototype.foo = "bar"; // add a property onto the prototype
var doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value"; // add a property onto the object
console.log( doSomeInstancing );

结果:

{
    prop: "some value",
    __proto__: {
        foo: "bar",
        constructor: ƒ doSomething(),
        __proto__: {
            constructor: ƒ Object(),
            hasOwnProperty: ƒ hasOwnProperty(),
            isPrototypeOf: ƒ isPrototypeOf(),
            propertyIsEnumerable: ƒ propertyIsEnumerable(),
            toLocaleString: ƒ toLocaleString(),
            toString: ƒ toString(),
            valueOf: ƒ valueOf()
        }
    }
}

就像上面看到的,doSomeInstancing 的 proto 属性就是doSomething.prototype. 但是这又有什么用呢?好吧,当你访问 doSomeInstancing 的一个属性,浏览器首先查找 doSomeInstancing 是否有这个属性。如果 doSomeInstancing 没有这个属性,然后浏览器就会在 doSomeInstancing 的 proto 中查找这个属性 (也就是 doSomething.prototype). 如果 doSomeInstancing 的 proto 有这个属性,那么 doSomeInstancing 的 proto 上的这个属性就会被使用。否则,如果 doSomeInstancing 的 proto 没有这个属性,浏览器就会去查找 doSomeInstancing 的 protoproto ,看它是否有这个属性。默认情况下,所有函数的原型属性的 proto 就是 window.Object.prototype. 所以 doSomeInstancing 的 protoproto (也就是 doSomething.prototype 的 proto (也就是 Object.prototype)) 会被查找是否有这个属性。如果没有在它里面找到这个属性,然后就会在 doSomeInstancing 的 protoprotoproto 里面查找。然而这有一个问题:doSomeInstancing 的 protoprotoproto 不存在。最后,原型链上面的所有的 proto 都被找完了,浏览器所有已经声明了的 proto 上都不存在这个属性,然后就得出结论,这个属性是 undefined.

例子:

function doSomething(){}
doSomething.prototype.foo = "bar";
var doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value";
console.log("doSomeInstancing.prop:      " + doSomeInstancing.prop);
console.log("doSomeInstancing.foo:       " + doSomeInstancing.foo);
console.log("doSomething.prop:           " + doSomething.prop);
console.log("doSomething.foo:            " + doSomething.foo);
console.log("doSomething.prototype.prop: " + doSomething.prototype.prop);
console.log("doSomething.prototype.foo:  " + doSomething.prototype.foo);

结果:

doSomeInstancing.prop:      some value
doSomeInstancing.foo:       bar
doSomething.prop:           undefined
doSomething.foo:            undefined
doSomething.prototype.prop: undefined
doSomething.prototype.foo:  bar

举报

相关推荐

0 条评论