如何在JavaScript中更改“this”指针?

时间:2016-12-23 00:47:39

标签: javascript jquery module

我做了这样一个对象:

var MyObj = function(arg)
{
  var PublicMethods = { 
          SomeMethod: function(someArg) 
          { 
            if(SomeCheck(arg)
            {
              PublicMethods.SomeFunc2 = somethingElse;
            }
          }
        };

  return PublicMethods;
};

但是MyObj似乎不是持久的,并且在调用之间,PublicMethods不会保留添加到它的新方法,所以我尝试将其移动到全局范围,但是它无法识别“args”再次从MyObj传来。

如果我像这样MyObj

var MyObj = (function()
{
//..
}());

然后它变成了一个持久对象,但我不确定 - 我可以再称它为函数吗? jQuery似乎有一个持久对象,同时它可以像函数一样被调用,它们如何实现呢?

我希望能够做到这一点:

MyObj("Something Here").SomeMethod("Something Else");

因此能够创建一个我以后可以调用的SomeFunc2方法:

MyObj("Something Here").SomeFunc2("Something Else");

2 个答案:

答案 0 :(得分:1)

只需将初始MyObj调用的结果存储在本地变量中:

var obj = MyObj("Something Here");
obj.SomeMethod("Something Else");
obj.SomeFunc2("Something else");

PublicMethods变量特定于MyObj的每次调用,因此当您第二次致电MyObj时,您会获得PublicMethods的不同实例。通过使用变量存储第一个MyObj调用的结果,您可以对PublicMethodsSomeMethod函数使用相同的SomeFunc2实例。

作为旁注,您可能需要查看constructor functions,它可以让您更简单地定义函数,而不是返回对象。例如:

function Example() {
    this.a = function() {
        return "a";
    };
    this.b = function() {
        this.a = function() {
            return "b";
        }
    }
}

var example = new Example();
example.a(); // => "a"
example.b();
example.a(); // => "b"

答案 1 :(得分:0)

您可以创建一个扩展jQueryjQuery.fn的jQuery方法,也可以在方法中设置this上下文。



(function($) {

  jQuery.addMethod = function addMethod({methodName, method, type}) {
  
    let bool = {
      [type]: false
    };
    
    let _jQuery_jQueryFn_ = Object.keys(bool).pop();
    
    if (type === "jQuery") {
      for (let prop in jQuery) {
        if (prop === methodName 
           || prop.toUpperCase() === methodName.toUpperCase()) {
                bool[type] = true;
                break;
        }
      }
    }

    if (type === "fn") {
      for (let prop in jQuery.fn) {
        if (prop === methodName 
            || prop.toUpperCase() === methodName.toUpperCase()) {
                 bool[type] = true;
                 break;
        }
      }
    }

    if (type === "jQuery" && bool[_jQuery_jQueryFn_] === false) {
      jQuery[methodName] = method;

    }

    if (type === "fn" && bool[_jQuery_jQueryFn_] === false) {
      jQuery[type][methodName] = method;
      
    }
    
    if (bool[_jQuery_jQueryFn_] === true) {
      return Promise.reject(
        new ReferenceError(
          methodName 
          + " previously defined at " 
          + _jQuery_jQueryFn_
      ));
      
    } else {
        console.log(methodName + " defined at " + _jQuery_jQueryFn_);
    }

    return {methodName:methodName, type}; 
  }
})(jQuery);

$(function() {

  Promise.resolve($.addMethod({
      methodName: "add",
      method: function add(a, b, context) {
        console.log(a + b);
        return (context || this)
      },
      type: "jQuery"
    }))
    .then(function({methodName, type}) {
      if (type === "jQuery" && methodName in window[type]) {
          jQuery[methodName](10, 10)
      } else {
        if (methodName in window["jQuery"][type]) {
          jQuery[type][methodName](10, 10);
        }
      }                   
    })
    .catch(function(err) {
      console.error(err)
    });

});

$(function() {

  Promise.resolve($.addMethod({
      methodName: "add",
      method: function add(a, b, context) {
        console.log(a + b);
        return (context || this)
      },
      type: "fn"
    }))
    .then(function({methodName, type}) {
      if (methodName === "jQuery" && methodName in window[type]) {
        jQuery[methodName](10, 10)
      } else {
        if (methodName in window["jQuery"][type]) {
          jQuery("span")[methodName](10, 10);
        }
      }      
    })
    .catch(function(err) {
      console.error(err)
    });

});

$(function() {
  
  
  Promise.resolve(
      $.addMethod({
        methodName: "reverseText",
        method: function reverseText(_text, context) {
          let text = [...(_text || this.text())].reverse().join("");
          (context || this).text(text);
          return (context || this)
        },
        type: "fn"
      }))
    .then(function({methodName, type}) {
      if (type === "jQuery" && methodName in window[type]) {
        jQuery[methodName]()
      } else {
        if (methodName in window["jQuery"][type]) {
          // set context `this` to `span`
          let span = jQuery("section")[methodName]("321", $("span"))    
          .css("color", "sienna");       
          
          console.log(
            span.is(document.querySelector("span"))
          );
        
          jQuery("section")[methodName]()
          .css("color", "green");
        }
      } 
    })
    .catch(function(err) {
      console.error(err)
    });

});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
</script>
<section>section</section>
<span>span</span>
&#13;
&#13;
&#13;