如何知道javascript或jquery中是否定义了对象?

时间:2013-10-29 07:21:08

标签: javascript jquery html ajax object

大家好我知道我的问题与其他问题类似但我的问题不同。请仔细听我说。

我只是想知道我是否一次又一次地调用一个函数如何在我的插件代码中设置一个条件,如果没有调用那个特定的部分就不会运行。

我在jQuery中编写了一个插件类型的短代码。这是我的项目特有的。 它适用于我在参数中传递的特定元素的集合widthheight。 在window loadwindow resize。 我是jquery的初学者,所以我不太熟悉对象。

这是代码

//creating some universal variable
var _W, _H, _header, _lH, _lW, _lH1, _lH2, _lH3;

(function($){
    adjust = function(options) {

    var defaults = { 
        headerClass: '',
        containerClass : '',
        Hlevel1:{space:0, divClass :'', prevDivClass : ''},
        Hlevel2:{space:0, divClass :'', prevDivClass : ''},
        Hlevel3:'',
        Wlevel1 : {space:0, divClass : '', prevDivClass : ''},
        Wlevel2 : {space:0, divClass : '', prevDivClass : ''}

    };
    var opts = $.extend(defaults, options);

    function performAdjust(){
            _W = $(window).width(); //retrieve current window width
            _H = $(window).height(); //retrieve current window height
            _headH = $(opts.headerClass).outerHeight(true);//retrieve current header height


            // take left height after header height subtract to window height
            _lH = _H - _headH

            //make a variable for level one height
            _lH1 = _lH - (opts.Hlevel1.space + $(opts.Hlevel1.prevDivClass).outerHeight(true))

            //make a variable for level two height
            _lH2 = _lH1 - (opts.Hlevel2.space + $(opts.Hlevel2.prevDivClass).outerHeight(true));



            //applying height on main container
            $(opts.containerClass).css({height:_lH});


            //applying height on level 1 div
            $(opts.Hlevel1.divClass).css({height:_lH1 });


            //applying height on level 2 div
            $(opts.Hlevel2.divClass).css({height:_lH2 });


            //take left width after level one element

            // if(typeof opts.Wlevel1.divClass === 'undefined'){
            //  console.log('insert in if');
            // }


            var prdiv_lw1 = $(opts.Wlevel1.prevDivClass).outerWidth(true);

            _lW1 = _W - (prdiv_lw1+ opts.Wlevel1.space);

            //applying Width on level 1 div
            $(opts.Wlevel1.divClass).css({width:_lW1 });


            //take left width after level one element
            _lW2 = _lW1 - ($(opts.Wlevel2.prevDivClass).outerWidth(true)+ opts.Wlevel2.space);
            //applying Width on level 2 div
            $(opts.Wlevel2.divClass).css({width:_lW2 });        

        };
        $(function() {
            performAdjust();
        });
        $(window).resize(function() {
            performAdjust();
        });

    }
})(jQuery);

如何初始化

// initialize adjust function for manage route
    $(document).ready(function (){
        adjust({
            headerClass : '.header',
            containerClass :'.container, .navContainer',
            Hlevel1: {space:0, divClass : '.viewport', prevDivClass : '#leftBreadcrumb'},

            Wlevel1 :{space:0, divClass : '.contentContainer', prevDivClass : '.navContainer'},
            Wlevel2 :{space:0, divClass : '.header-midsec', prevDivClass : '.navContainer'}
        })
    });

当页面来自ajax请求时再次初始化

$(document).ready(function (){
  adjust({
    Hlevel1: {space:100, divClass : '.viewport1', prevDivClass : '.routeHead '},
  })
});

问题

当我再次为其他元素初始化它时,它将覆盖所有属性。 我第一次初始化主页面结构。下次我的页面来自ajax请求,因此在该结构下面有一些元素需要动态width, height来调整这个我再次初始化它但它将覆盖所有属性。

如果我再次调用此函数并且不传递未使用的对象和参数,那么我想提出一个条件。

我如何实现这一点请告诉我

提前致谢并抱歉我的英文

我只是想知道我是否一次又一次地调用一个函数如何在我的插件中设置一个条件,如果没有调用那个特定的部分就不会运行。

我尝试了typeof还有一件事,但我无法理解如何处理它。

2 个答案:

答案 0 :(得分:2)

如果我理解正确的话,你实际想要实现的是,在第一次使用传递的选项字段覆盖默认值,但在再次执行时覆盖上次使用的值。

您想要做的是,简单地将defaults变量移出到闭包的范围,超出adjust函数的范围。这样,新的传入options字段将覆盖先前使用的对象,而不是每次都覆盖相同的硬编码默认值。

基本上,你改变了:

adjust = function(options) {
    var defaults = { 
        headerClass: '',
        containerClass : ''
    };
    var opts = $.extend(defaults, options);

为:

var defaults = { 
        headerClass: '',
        containerClass : ''            
    };

adjust = function(options) {
    var opts = $.extend(defaults, options);

JSFiddle示例:http://jsfiddle.net/MvxAj/1/

为了便于阅读,我删除了XlevelY字段。您可能还需要考虑使用更加动态的方法,其中这些字段不是硬编码的,以便在添加其他级别时最小化代码更改,但这是另一种情况:)

答案 1 :(得分:1)

可能的解决方案

我猜你需要的只是对设置的特定值进行一些条件检查,但是你的代码读起来相当笨拙,所以找出需要定义的内容来触发什么操作有点困难。

代码中的主要常量似乎是为您定位的每个元素定义了一个特定的选择器,因此您可以使用if:

将每个影响特定选择器的语句包装起来。
if ( opts.containerClass ) {
  $(opts.containerClass).css({height:_lH});
}

你真的不需要typeof因为如果你的选择器是空的,它们将不会非常有用......并且空格被false计为if {1}}陈述。

但是,如果您有任何相互依赖的元素进行大小更改,则不会考虑这一点,您的代码逻辑和css必须知道元素之间的依赖关系,并相应地应用if语句。

进一步的问题

默认对象也会增加一个问题,因为如果将一组默认值合并到正在测试属性存在的对象,则默认对象中的属性将始终显示为set。你有三种解决方法。

  1. 在合并默认值之前创建测试对象,然后从此测试对象运行所有if语句。
  2. 仅在第一次调用代码时使用默认对象,后续调用只依赖于您传入的内容。
  3. 稍后在ajax之后调用代码时,请为您不想更改的项传入false值。
  4. 所以作为1的示例,将此代码放在默认合并之前。

    var test = {};
    if ( options.containerClass ) {
      test.containerClass = true;
    }
    var opts = $.extend({}, defaults, options);
    

    然而,如果您不需要使用它们,使用默认值会显得有些愚蠢,当您在ajax之后调用时可能就是这种情况;这引导我们进入第2点:

    if ( !adjust.alreadyCalled ) {
      var opts = $.extend(defaults, options);
      adjust.alreadyCalled = true;
    }
    else {
      opts = options;
    }
    

    有些人可能会抱怨上述想法,因为它会以一种意想不到的方式改变你的adjust方法的行为。这就是为什么我建议第3点 - 覆盖你不想要的项目 - 如果你愿意的话。

    $(document).ready(function(){
      adjust({
        containerClass: false,
        Hlevel1: {
         'space': 100, 
         'divClass': '.viewport1', 
         'prevDivClass': '.routeHead '
        }
      })
    });
    

    这样做的缺点是,如果您扩展了此功能可以调整的项目,您将不得不修改所有调用以进行调整,以确保您要覆盖的所有内容都是falsed

    更好的方法

    而不是解决你已经拥有的东西,我建议的 - 以及条件语句的添加 - 是为adjust添加一个辅助参数,例如:

    adjust = function(options, includeDefaults) {
    

    通过这种方式,您可以判断是否以及何时使用默认值,显然如果启用默认值,则可能会发生所有调整...如果您不启用默认值,则可以更具体地说明你想调整,因为你的条件检查不会被默认值混淆。

    var opts;
    if ( includeDefaults ) {
      opts = $.extend({}, defaults, options);
    }
    else {
      opts = options;
    }
    

    更新

    @ikari(+1)只是提出了一个我没注意到的好点,你实际上没有正确地使用$.extend进行默认合并。你最好使用:

    opts = $.extend({}, defaults, options);
    

    通过这种方式,您可以创建一个新对象,首先组合默认值,然后组合传入的选项,而不是不断修改默认对象。我已经完成并更新了上面的代码以反映这一变化。