开发者

What's the scope of parameters of a function set by onclick?

I've a function which accept only html string, it will show a info window (a popup) with the html as its content:

function createInfoWindow(info_html){
    // show a popup with info_html as its content
}

Now I want to create a info window which will have a button:

function createMyInfoWindow(o){
    var info_html = "<开发者_高级运维input type='button' value='click me' onclick='foo(o)'>"
    createInfoWindow(info_html);
}    

function foo(o){
    console.log(o);
}
createMyInfoWindow({ name: "test", age: 21);

However, when I click the button, it says that o can't be found.


Try following code

var info_html = "<input type='button' value='click me' onclick='foo(\""+o+"\")'>"

UPDATE

If o is object it becomes more complicated.

You can store passed objects in store-object. Then you can pass corresponding index in foo:

var storage = [];
function createMyInfoWindow(o){
    var index = storage.length;
    storage[index] = o;
    var info_html = "<input type='button' value='click me' onclick='foo(\""+index+"\")'>"
    createInfoWindow(info_html);
}    

function foo(i){
    console.log(storage[i]);
}
createMyInfoWindow({ name: "test", age: 21);


In the HTML assigned to the innerHTML of the input, handlers are wrapped in functions so the scope is the handler, then global (there may be other objects on the scope chain).

In your code, name is local to createMyInfoWindow, the handler (nor any other function) has access to that variable. See Molecule's answer for how to use it.


The way you are doing it now is a form of eval, and is generally frowned upon. Read up on Unobtrusive Javascript if you'd like to know all the reasons why.

However, there is a really excellent way to accomplish the same task without the scope problems your facing (let alone trying to get that object passed to the function in string form -- yikes!) Doing this properly will require some restructuring of your functions, but I'm sure you'll find it to be worth it.

function createMyInfoWindow(o){
  // creating window first so we can access it from the DOM
  createInfoWindow(info_html);
  // we can select the window from the DOM now, but it would be even better if
  // createInfoWindow returned that object so we could just pick up where we left off
  var myInfoWindow = document.getElementById("myInfoWindow");

  // The button you are putting into the window
  var myButton = document.createElement("input");
  myButton.type = "button";
  myButton.value = "click me";
  // because of javascript closures, we can call foo(o) from within an anonymous function
  myButton.onclick = function () { foo(o) };
}

I prefer creating HTML elements this way for many reasons: 1) Avoid the implicit use of eval, 2) much easier to debug the HTML when it is generated by the javascript for you and 3) no more scope issues for event functions.

You just have to create the window in the reverse order now, because the window element must exist first in order to add a button to it, and the button element must exist before you can add the onclick handler to it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜