requireJS对象原型可能只是一个Object或null -jQuery

时间:2016-02-24 18:21:31

标签: javascript jquery object requirejs

我遇到了requireJS的问题。我试图加载jQuery和我的其他脚本,但我收到一个错误。这是代码:

的index.html

<!DOCTYPE html>
<html lang="en">
    <head></head>
    <body>
        <script data-main="./app" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.min.js">  </script>
    </body>
</html>

app.js

(function(){
    'use strict';

    require.config({
        paths: {
            jQuery: 'https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min',
            helpers: 'helpers',
        },
        shim: {
            jQuery: {
                exports: '$'
            }
        }
    });

    requirejs(['main']);
})();

main.js

define(function(require){
    require(['jQuery', 'helpers'], function($){
        $('body').css({'background': 'red'});
    });
});

helpers.js

define(function(){
    'use strict';

    Object.prototype.extend = function(parentClass){
        if(!Object.create){
            Object.prototype.create = function(proto){
                function F(){}
                F.prototype = proto;
                return new F();
            };
        }
        this.prototype = Object.create(parentClass.prototype);
        this.prototype.constructor = this;
    }
});

我收到以下错误: Uncaught TypeError: Object prototype may only be an Object or null: undefined helpers.js 的第12行看起来,一旦需要jQuery,它就会触发所有的Object.prototype属性。这是因为:

define(function(){
    'use strict';

    Object.prototype.extend = function(parentClass){
        alert('This code shoud be executed only when called on objects!');
        if(!Object.create){
            Object.prototype.create = function(proto){
                function F(){}
                F.prototype = proto;
                return new F();
            };
        }
        this.prototype = Object.create(parentClass.prototype);    //The error occurs here because the code in the scope is executed and parentClass is undefined
        this.prototype.constructor = this;
    }
});

在extend方法中警告消息。为什么?如果没有使用requireJS,jQuery可以正常使用我的脚本。有什么帮助吗?

文件结构:

testAppFolder

  • 的index.html

  • app.js

  • helpers.js

  • main.js

2 个答案:

答案 0 :(得分:2)

你真的不应该混淆Object.prototype。您遇到的问题只是一个可能导致的许多问题。 正确解决您的问题的方法是使用另一种方法,而不是将extend添加到Object.prototype

为什么不起作用?当您执行Object.prototype.extend = function () {...时,您要在Object.prototype上声明新属性,默认情况下,此属性为可枚举。这意味着,如果您执行for (var i in {}) console.log(i);后,此任务生效后,您将在控制台上获得extend

现在,jQuery有一个名为extend的好函数。有趣的是,当jQuery初始化时,它使用jQuery.extend来扩展自己。如果你看一下jQuery源代码,你会看到类似的东西:

jQuery.extend( {
    expando: ...,
    isReady: ...,
});

当仅使用一个参数调用extend时,这意味着要展开的内容为this,即jQuery本身。因此extend将传递的对象作为参数传递,并使用for...in循环遍历其属性。哪一个很好,直到它遇到你添加到extend的{​​{1}}。当它到达此属性时,它会使用Object.prototype中的方法覆盖自己的extend方法。因此,下次运行 Object.prototype时,它会运行您分配给jQuery.extend的代码,并且您会收到错误。

您还应该将jQuery模块称为Object.prototype.extend而不是jquery,并删除jQuery配置。 jQuery调用shim(因此没有define),并将其名称硬编码为shim。有关详细信息,请参阅my answer to another question

以下仅供参考。请勿在生产代码中使用。

如果您使用以下代码替换jquery,则问题将会消失:

helpers.js

这使用Object.definePropertydefine(function() { 'use strict'; Object.defineProperty(Object.prototype, "extend", { value: function(parentClass) { if (!Object.create) { Object.defineProperty(Object.prototype, "create", { value: function(proto) { function F() {} F.prototype = proto; return new F(); }, enumerable: false, writable: true }); } this.prototype = Object.create(parentClass.prototype); this.prototype.constructor = this; }, enumerable: false, writable: true }); }); 定义为不可枚举的属性,因此它不会显示在extend中。它也是可写的,它允许jQuery定义自己的for...in。它对jQuery.extend也是如此。

答案 1 :(得分:0)

我发现将方法直接附加到对象不是一个好习惯。因此,我创建了自己的库,如:

define(function(){

    var _ = (function(){
        'use strict';

        function _(o){
            if(!(this instanceof _)){
                return new _(o);
            }
            this.o = o;
        }

        _.isArray = function(arg){
            return Object.prototype.toString.call(arg) === '[object Array]';
        };

        _.prototype = {

            extend: function(parentClass){
                if(!Object.create){
                    Object.prototype.create = function(proto){
                        function F(){}
                        F.prototype = proto;
                        return new F();
                    }
                }
                this.o.prototype = Object.create(parentClass.prototype);
                this.o.prototype.constructor = this;
            }

            // Other methods here

        };

        return _;
    })();

    return _;
});

并使用那样:

var MyClass = (function(){ ... })();
var MyOtherClass = (function(){
    _(MyOtherClass).extend(MyClass);

    function MyOtherClass(){
        //constructor
    }

    return MyOtherClass;
})();

不再有错误:)