我遇到了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
答案 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.defineProperty
将define(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;
})();
不再有错误:)