首页 新闻 会员 周边 捐助

这个函数执行 为什么取不到外部的值

0
[已解决问题] 解决于 2017-10-13 23:01
<!DOCTYPE html>
<html lang="en">

 

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>

 

<body>

 

</body>

 

<script>
var name = '张三';
(function () {
if (typeof name == 'undefined') {
var name = '李四';
console.log(name);
} else {
console.log('hello' + name);
}
})()
</script>
</html>
 
 
主要的疑虑就是为什么取不到外部的值,以及这个函数前后两个括号各代表的是什么意思?
这样会形成闭包吗?
 
劳烦哪位大佬给我解答,谢谢了~~
奋斗的少年-欧耶的主页 奋斗的少年-欧耶 | 菜鸟二级 | 园豆:214
提问于:2017-10-13 15:34
< >
分享
最佳答案
0

简单点,先去掉判断,这样写:

<script>
var name = '张三';
function test(){

var name1 = name;
console.log(name1);

}
test();
</script>

上面看懂了,再加上判断即可。

奖励园豆:5
ycyzharry | 高人七级 |园豆:25683 | 2017-10-13 16:09

这个函数是可以看懂的,但是不懂的是:

1、

var name = '张三';
(function () {
 
console.log(typeof name);
console.log(name);
 
})()
 
2、
var name = '张三';
(function () {
 
 if (typeof name == 'undefined') {
 var name = '李四';
 console.log(name);
 } else {
 console.log('hello' + name);
}
 
})()
 
现在不懂的是 为什么第一种是可以访问 name 的数据类型,而第二种访问不到 name 的数据类型,正常第一种显示 name 的数据类型已经是 string 了 下面代码 if 判断的时候 typeof name 应该也是 string  可结果是 undefined  
奋斗的少年-欧耶 | 园豆:214 (菜鸟二级) | 2017-10-13 17:17

@奋斗的少年-欧耶: 。。看来你还是不明白var 在作用域开始的时候会被提前到最前面执行么。。

 

比如说

var a = 1;

function(){

    console.log(a); 

    var a = 0;
    console.log(a); 
}

 

会打印undefined 0

 

是因为函数运行的时候发生了变化 var 定义变量被提前了

运行后的函数是这样的

var a = 1;

function(){

    var a = undefined;

    console.log(a);   //这里根据就近原则会现在本域中查找a 变量 如果没有就去上一级查找a变量直至全局变量window里面也没有就返回报错。 不存在; 因为运行到这里的时候a 还没赋值  所以打印undefined

    a = 0;
    console.log(a);   // 这里的时候 因为赋值了0  所以 打印结果0
}

全程因为 运行域内部有变量a 导致外面的域的a变量根本用不上 

blurs | 园豆:660 (小虾三级) | 2017-10-13 18:47

@blurs: 哦哦  这个我理解了  变量提升所导致的   但是我又碰到一个问题  就是在最外层 设置一个变量 name 不给他赋值  同时  typeof name   所显示的   是 string 不是 undefined 这个是怎么回事啊?

奋斗的少年-欧耶 | 园豆:214 (菜鸟二级) | 2017-10-13 21:48

@blurs: 那个  我知道了   原来是window 对象下的 name 属性  是字符串    非常感谢大佬的帮助   谢谢了~~

奋斗的少年-欧耶 | 园豆:214 (菜鸟二级) | 2017-10-13 22:20
其他回答(1)
1

。。。因为迷路了  人家线程走的好好的突然发现前面有一个name 咦 这家伙比较近 就是他了 然后就把他拿了过来一看  咦? 还没赋值的undefined?那就没办法了 给他赋值一个李四吧

 

好啦 玩笑开在这里

简单的来说 这里有一个基础知识

每一个函数作用域 被执行(也就是被调用的时候【后面加了一个()】) 都会产生一个活动域(作用域) 这个域被激活的一瞬间 他会经历3个阶段

阶段一 : 创建  arguments this 变量(活动变量) 

阶段二 : 扫描全部定义变量然后创建空变量 (比如你这个name 就算你写在了下面 但是 只要让这个域检测到var name了,不好意思 都会在第一时间帮你定义好,至于你的=“李四” 它才不会管呢,他只管创建不管赋值。这个时候就有了 一个区域变量name=undefined ,)

阶段三 :开始走逻辑流程了(一般的小白都会觉得函数是从这里开始的。。。)

阶段三的时候  他先进入你的if判断 name 还真特么是undefined  那敢情好, 咱们给他赋值李四 好的  然后打印李四。

blurs | 园豆:660 (小虾三级) | 2017-10-13 15:56
这是你那个函数内部还没执行的时候的样子
if (typeof name == 'undefined') {
  var name = '李四';
  console.log(name);
} else {
  console.log('hello' + name);
}
 
第一阶段的时候变成了
this = window;
arguments = [];
if (typeof name == 'undefined') {
  var name = '李四';
  console.log(name);
} else {
  console.log('hello' + name);
}
 
第二阶段的时候
this = window;
arguments = [];
var name = undefined; //注意这里是undefined 不是null null表示不存在 undefined表示未赋值等待赋值中;
if (typeof name == 'undefined') {
  name = '李四';
  console.log(name);
} else {
  console.log('hello' + name);
}
 
第三阶段
不用看了 输出李四 因为这个函数没有返回return  会默认一个undefined  所以结论是 李四 下面一个 undefined
支持(0) 反对(0) blurs | 园豆:660 (小虾三级) | 2017-10-13 16:02

@blurs: 嗯嗯   但是如果是这样的话就会访问到外部的 name 值以及外部name的数据类型,这种和之前的 if 判断语句里面的 typeof name 为什么会不一样啊? 为什么如下的函数可以访问,之前的那种写法就不能访问呢?   

var name = '张三';
(function () {
 
// 这里面的 this 指向的是 Window 对象 是因为这个函数挂载在 Window 对象下面吗? 
 
console.log(typeof name);
console.log(name);
 
})()
支持(0) 反对(0) 奋斗的少年-欧耶 | 园豆:214 (菜鸟二级) | 2017-10-13 17:12

@奋斗的少年-欧耶: 局部变量和全局变量重名会覆盖全局变量...应该没有错吧?

支持(0) 反对(0) hehe_54321 | 园豆:950 (小虾三级) | 2017-10-13 17:56

@hehe_54321: 您的意思是说 if 里面的 typeof name 将 name 覆盖了吗? 但是我不加 if 判断直接console.log 是可以获取到 name 的数据类型 以及 name 值的  这怎么解释啊?  

支持(0) 反对(0) 奋斗的少年-欧耶 | 园豆:214 (菜鸟二级) | 2017-10-13 18:06

@奋斗的少年-欧耶: 我再讲一遍层主的意思吧,函数被执行时,首先扫描函数体中全部对变量的var定义,然后定义好这个变量(但是不进行赋值,也就是创建了一个值为undefined的变量,也就是说你在这个函数之中如果在赋值之前访问到这个名字的变量,不会访问到同名全局变量的值,只会访问到这个undefined值的变量),然后执行函数体,如果有var ...=...实际操作就相当于直接赋值(...=...)。

typeof name不会把name覆盖,是函数体中定义的name把全局的name覆盖了。js不是c++

支持(0) 反对(0) hehe_54321 | 园豆:950 (小虾三级) | 2017-10-13 18:16

@hehe_54321: 并不会哟  覆盖只会出现在同一个域类 相同变量名的时候才会出现。  

支持(0) 反对(0) blurs | 园豆:660 (小虾三级) | 2017-10-13 18:41

@blurs: 这个  我终于知道是怎么回事了  谢谢大佬们的帮助了   非常感谢~~

支持(0) 反对(0) 奋斗的少年-欧耶 | 园豆:214 (菜鸟二级) | 2017-10-13 22:21
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册