首页 > 请教一下,在一个函数内,给HTML元素添加行内click事件,click发生时,为什么访问不到这个函数的局部变量。

请教一下,在一个函数内,给HTML元素添加行内click事件,click发生时,为什么访问不到这个函数的局部变量。

为什么弹出的是“外面”,而不是“内部”?

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>行间事件测试</title>
<style>
*{margin: 0; padding: 0;}
div{width: 300px; height: 40px;
    border: 2px solid orange;
}
span{background: lime;}
</style>
</head>
<body>
    <div>
    </div>
<script> 
    // 获取到div节点
    var oD=document.body.children[0];
    // 变量temp 存着字符串“外面”
    var temp='外面';
    // 定义一个函数f
    function f(){ 
        // 局部变量temp 保存着'内部'
        var temp='内部';
        oD.innerHTML='<span onclick="obj.m(temp)">js代码添加的</span>';
    }
    // 定义一个对象 及 它的方法
    var obj={};
    obj.m=function(type){
        alert(type); 
    };
    // 调用f
    f();
</script>    
</body>
</html>

附图:


你这样当然是访问不到的。

oD.innerHTML='<span onclick="obj.m(temp)">js代码添加的</span>';

--当你这样写的时候,生成的html代码是: obj.m(temp)

此时,这里的temp就是js里面的temp变量,也就是你声明的那个全局变量,所以值为‘外面’。跟 f()这个函数没半毛钱关系,所以跟f()里面的temp变量更没关系。

**如果你的目的是:在obj.m()中获取f()函数内部temp的值,你需要这样写:
oD.innerHTML='<span onclick="obj.m(''+temp+'')">js代码添加的</span>';**
这样写的意思是:将f()里面的temp传递给了 obj.m()这个函数。
此时生成的html代码就是: obj.m('内部')


局部作用域和全局作用域你没有理解,点击按钮的时候是外部定义的temp,里面的temp不起任何作用。
代码也需要看上下文情景


这样写就是“内部”

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>行间事件测试</title>
<style>
*{margin: 0; padding: 0;}
div{width: 300px; height: 40px;
    border: 2px solid orange;
}
span{background: lime;}
</style>
</head>
<body>
    <div>
    </div>
<script> 
    // 获取到div节点
    var oD=document.body.children[0];
    // 变量temp 存着字符串“外面”
    var temp='外面';
    // 定义一个函数f
    function f(){ 
        // 局部变量temp 保存着'内部'
        var temp='内部';
        oD.innerHTML='<span>js代码添加的</span>';
        document.querySelector("span").onclick=function(){
            obj.m(temp)
        }
    }
    // 定义一个对象 及 它的方法
    var obj={};
    obj.m=function(type){
        alert(type); 
    };
    // 调用f
    f();
</script>    
</body>
</html>

你这样写,实际上在调用obj.m这个方法的时候 f函数内部的作用域已经被销毁了,内部temp变量已经不存在了。要形成闭包需要内部函数保存外部函数的引用,'<span onclick="obj.m(temp)">js代码添加的</span>',这样的写法在onclick调用之前obj.m就只是一个字符串。你可以把obj.m这个对象和方法都放到函数内部声明。你会发现会报错 obj对象不存在。要保存f函数内部temp变量不被销毁。你需要在调用事件处理器时引用它。代码@getAnswer (楼上)已经贴出来了。

document.querySelector("span").onclick=function(){
            obj.m(temp)
        }

js函数的域不是在声明函数时所在的域的而是函数被执行时候的所在域


这个,我有一些浅显的理解:
当你执行f()这个方法的时候其实是这样调用的window.f();
所以在当前的上下文是window,当点击调用这个方法的时候temp这个变量拿的始终是全局变量‘外部’
其实你去掉f方法里面的对temp的var声明就行了,然后里面的temp会直接把全局变量temp的值覆盖掉
拿到的就是内部了,不去掉var的话全局变量temp是不能被方法里面的变量所覆盖的,所以拿到的是‘外部’。

这里牵扯到很多知识的
1 上下文
2 函数和变量的提前
等等

所以你只需要把f方法里面对temp的声明去掉即可
function f(){

// 局部变量temp 保存着'内部'
temp='内部';
oD.innerHTML='<span onclick="obj.m(temp)">js代码添加的</span>';

}


因为var temp='内部'是f()中的局部变量,obj.m指向了匿名方法引用,不能访问f()方法中temp变量。所以使用了全局变量temp,值为'外部'。


当你执行obj.m时候,实际该函数再进行DOM树绘制时候是把temp当作变量来看的,因此会先寻找temp变量,如果没有找到则是undefined的,我觉得楼主的的目的是这样?

function f(){ 
        // 局部变量temp 保存着'内部'
        var temp='内部';
        oD.innerHTML='<span onclick="obj.m("' + temp + '")">js代码添加的</span>';
    }
【热门文章】
【热门文章】