我为网站开发了某种Jcrop初始化,我设法创建了自己的命名空间.我的问题是关于这个关键字.每次我必须在任何回调函数中访问我的基础对象“aps”时,我必须将它包装在一个变量中(我选择了这个单词).有没有更好的方法呢?例如,我可以使用call或apply方法吗?这只是一个命名空间,所以我可以使用简单的aps.methodName但是为了这个例子,请不要介意.这是我的源代码:
var aps; $(function(){ aps = function(){ // private // variables var bgColor = '#f5f5f5'; var threshold = 370; var threshold_width = 800; return { tmpl : $('#jcrop-template').html(),upl_cont : {},form : {},logo_img : new Image(),jcrop_api : null,scaled_logo_url : '',image_filename : '',original_image_filename : '',mime : '',trueSize : '',jcrop_init : function (oiFrameRes){ $('#logo_upload_form').find('img').hide(); this.scaled_logo_url = oiFrameRes.image_url; this.logo_url = oiFrameRes.original_image_url; this.original_image_filename = oiFrameRes.original_image_filename; this.image_filename = oiFrameRes.image_filename; this.mime = oiFrameRes.mime; this.upl_cont = $('#faceBox div#upload-container-d'); this.logo_img = new Image(); this.logo_img.that = this; this.logo_img.name = 'logo'; this.logo_img.onload = function(){ this.true_width=this.width; this.true_height=this.height; this.that.resize_image(); this.that.resize_faceBox(); this.that.display_image(); } this.logo_img.src = this.logo_url; },resize_image : function(){ this.trueSize = ''; if(typeof (this.oSettings.trueSize)!=='undefined') delete(this.oSettings.trueSize); if (this.logo_img.width > threshold){ if (this.logo_img.width > threshold_width){ this.trueSize = [ this.logo_img.width,this.logo_img.height ]; this.logo_img.height = this.logo_img.height / (this.logo_img.width / threshold_width); this.logo_img.width = threshold_width; } } },resize_faceBox : function(){ var width = (this.logo_img.width > threshold) ? this.logo_img.width : threshold ; $('#faceBox').css({ left : $(window).width() / 2 - width / 2 }). find('div.change-size').css({'width': width+30}); },display_image : function (){ if (this.jcrop_api === null) { $logo_img = $(this.logo_img).css({'display':'block','margin-left':'auto','margin-right':'auto'}) if (this.upl_cont.find('#logo-container-d>img').length > 0){ if (this.upl_cont.find('#logo-container-d>img').attr('src').length > 0){ this.upl_cont.find('#logo-container-d').empty().append($logo_img); } } else { this.upl_cont.append(this.tmpl).find('#logo-container-d').append($logo_img); } var that = this; if (typeof (this.upl_cont.find('#jcrop-menu1 a').data('events')) === 'undefined'){ this.upl_cont.find('#jcrop-menu1 a').click(function(){ if (this.href.indexOf('#crop')>-1){ $(this).closest('div').hide(); that.upl_cont.find('#jcrop-menu2').show(); that.setup_crop(); } if (this.href.indexOf('#close')>-1){ manageIframeResponse(); } location.hash = ''; return false; }); } } else { this.reset(); } },reset : function(){ $('#jcrop-menu2',this.upl_cont).find('a').unbind('click').end().hide(); $('#jcrop-coords-f',this.upl_cont).find('input[type="text"]').each(function(){this.value="";}).end().hide(); $('#jcrop-menu1',this.upl_cont).find('a').unbind('click').end().show(); this.jcrop_api.destroy(); this.jcrop_api=null; this.display_image(); },send_form : function (){ var sPost = $(this.form).find('input[name="image_filename"]').val(this.image_filename).end() .find('input[name="original_image_filename"]').val(this.original_image_filename).end() .find('input[name="mime"]').val(this.mime).end() .find('input[name="user_url"]').val($('#logo_upload_base_url').val()).end() .find('input[name="user_key"]').val($('#logo_upload_user_key').val()).end() .serialize(); $.ajax({ url:'iframe_upload.PHP',type:'POST',data: sPost,success : function(response){ manageIframeResponse(); },dataType : 'json' }); },setup_crop : function (){ var that = this; if (this.jcrop_api === null) { this.form = this.upl_cont.find('form#jcrop-coords-f').get(0); this.upl_cont.find('#jcrop-menu2>a').click(function(){ that.send_form();return false; }); this.updateForm = function (){ var c = arguments[0]; that.form.x1.value=c.x; that.form.x2.value=c.x2; that.form.y1.value=c.y; that.form.y2.value=c.y2; that.form.h.value=c.h; that.form.w.value=c.w; } this.oSettings.onSelect = this.updateForm; if (typeof (this.trueSize) !== 'string' && $.isArray(this.trueSize)){ $.extend(this.oSettings,{'trueSize':this.trueSize}); } $('#faceBox #logo-container-d>img').Jcrop( this.oSettings,function(){ that.jcrop_api = this; var _x1 = (that.logo_img.true_width*0.1).toFixed(); var _y1 = (that.logo_img.true_height*0.1).toFixed(); var _x2 = (that.logo_img.true_width*0.9).toFixed(); var _y2 = (that.logo_img.true_height*0.9).toFixed(); that.jcrop_api.setSelect([0,that.logo_img.true_width,that.logo_img.true_height]); that.jcrop_api.animateTo([_x1,_y1,_x2,_y2]); }); } },updateForm : function (){},oSettings : { onSelect:'',onChange:'',keySupport: false,bgColor:bgColor,aspectRatio:1,minSize:[0,0] } } }(); $(document).bind('afterClose.faceBox',function() { if (aps.jcrop_api !=null) { aps.jcrop_api.destroy(); aps.jcrop_api=null; } }); });
解决方法
无论何时使用函数调用*调用函数,此值都将设置为全局变量(或在严格模式下未定义) – 即使从方法调用函数也是如此.道格拉斯·克罗克福德实际上已将此描述为该语言的一个缺陷.
如果您真的想控制回调中的内容,可以使用apply或call.两者都将您想要设置的第一个参数作为第一个参数.不同之处在于apply期望所有函数的参数作为数组传递,而call期望您单独列出它们.
因此,如果在你的ajax回调中,你想调用manageIframeResponse,请传递ajax调用的响应(我知道你的例子没有传递响应,我只是说明你将如何做),并将其值设为与当前对象相同,您可以这样做:
var self = this; $.ajax({ success : function(response){ manageIframeResponse.apply(self,[response]); //<--- apply wants your arguments in array form } });
或者,由于您的参数尚未采用数组形式,因此您可以更简单地使用调用
var self = this; $.ajax({ success : function(response){ manageIframeResponse.call(self,response); //<---call takes the arguments listed out one at a time } });
foo() //inside foo,this will be the global object (or undefined in strict mode)
myObj.foo() //inside foo,this will be myObj
这里有一个例子,如果你不小心,这会让你感到沮丧.
function objCreator() { var y = "There"; function privateFunc() { alert(y); //alerts There as expected alert(this.someField); //undefined: whoops - this is the global object,} //so there's no someField return { x: "Hi",someField: "blah",foo: function () { alert(this.x); privateFunc(); } }; }