ES6中函数的作用域问题

news/2024/7/11 1:06:10 标签: ES6, 函数作用域

前言:ES6中规定函数参数可以使用默认值,其参数可与解构赋值的默认值结合使用,且函数此时的length属性返回的是无指定默认值参数的个数

注意: 一旦设置参数默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。

//题一
let x = 1;
function f(y) {//这个参数y和下面函数内部是属于同一个作用域的(因为此时函数参数没有默认值) 
    let x = 2;   //这个x在函数作用域内,和最外层的x=1不是同一个作用域,可以再次声明
    y=x;
    console.log(y);
}
f();//2
//题二
let x = 1;
function f(y = x) {//参数`y = x`形成一个单独的作用域
  let x = 2;   //和上面的x不是同一个作用域,所以可以重复声明
  console.log(y);
}
f() // 1
//题三
//y和外面的x值是一样的,在函数内部没有重新给y赋值!!!
let x;
function f(y = x) {//参数`y = x`形成一个单独的作用域
    let x = 2; 
    console.log(y);
}
f() // undefined

//注意在同一作用域里面千万不能重复声明
let x = 99;
let x = 100;//Identifier 'x' has already been declared

上面代码中,函数f调用时,参数y = x形成一个单独的作用域。这个作用域里面,变量x本身没有定义,所以指向外层的全局变量x。函数调用时,函数体内部的局部变量x影响不到默认值变量x
下面是一个更复杂的例子。

//我终于明白了,哈哈哈
var x = 1;  //第一层
//在函数参数里面,都默认声明,属于第二层作用域
function foo(x, y = function() { x = 2; console.log(x);}/*第二层*/) {
    var x = 3;  //在此又声明一次,属于第三层作用域
    y(); //2,但是是在第二个作用域里面
    console.log(x); //是第三个作用域里面的值 3
}

foo() // 2 3
console.log(x) // 1

上面代码中,函数foo的参数形成一个单独作用域。这个作用域里面,首先声明了变量x,然后声明了变量yy的默认值是一个匿名函数。这个匿名函数内部的变量x,指向同一个作用域的第一个参数x。函数foo内部又声明了一个内部变量x,该变量与第一个参数x由于不是同一个作用域,所以不是同一个变量,因此执行y后,内部变量x和外部全局变量x的值都没变。

如果将var x = 3var去除,函数foo的内部变量x就指向第一个参数x,与匿名函数内部的x是一致的,所以最后输出的就是2,而外层的全局变量x依然不受影响。

var x = 1; //第一层
function foo(x, y = function() { x = 2;/*第二层*/ }) {
  x = 3; //没有声明,属于上一层作用域,即属于第二层
  console.log(x); //此时x值为3
  y(); //实例化后,x值变为2
  console.log(x);  //2
}
foo(); //3 2
console.log(x) // 1

函数参数中有无的影响:

//第一种情况:函数中有参数x
var x = 1; //第一层
function foo(x) { //其实x在此处是声明了的,所以x是局部变量
    x = 3; //局部变量 function内部是一个单独的作用域,这个值不影响全局
    console.log(x);
}
foo() // 3
console.log(x);  //1

//第二种情况:函数中没有参数x
var x = 1; //第一层
function foo() {
    x = 3; //此时x才是真正的全局变量
    console.log(x);
}
console.log(x);  //1 因为函数没有实例化,所以x还是原来的值
foo()// 3
console.log(x);  //3 实例化后,x就是改变过后的值

http://www.niftyadmin.cn/n/892439.html

相关文章

咖啡的香气

大疆2019年8月4日21:05:27 假设每喝一杯咖啡(喝咖啡时间忽略不计)就能让自己debug效率提高A倍,一小时内重复喝没用,最多只能喝X杯(太多晚上睡不着),并且为了可持续发展,每天最多只能…

JS面试题:判断一个对象{}是否为空对象的五种方法

//判断对象是否为空的几种方法 let a {}; let b{cc: 1} //法一:将json对象转化为json字符串,再判断该字符串是否为"{}" console.log(JSON.stringify(a){})//true console.log(JSON.stringify(b){})//false //法二:for in 循环判断…

N行M列每个位置放Aij个1厘米的正方体,求表面积

2019年8月15号 21点15分 360笔试编程题 本题考虑不周,有点错误,待解决。。。。 题目如下: 思路:分别从三个方向来看, 从上往下看,定有面积 N*M;从正面看,面积是每一列最高的数相…

Vue中 axios delete请求参数

转自Vue中 axios delete请求参数 vue中axios 的delete和post,put在传值上有点区别; post和put有三个参数,url,data和config,所以在使用这两个时,可以写成axios.post(api,{id:1}),axios.put(api,{id:1}),但是delete只有两个参数:ur…

2048游戏 JavaScript实现

字节跳动笔试题 参考Google2015校园招聘在线笔试题2–2048游戏 k记录要被放置的位置索引 1.k位置元素是0,将e[i]移到e[k] 2.k位置非零: (1)e[i]e[k]相同,碰撞,e[k]2,k移到下一个位置&#xf…

十进制转为7进制、打印金字塔111 JS语言描述

阿里 2019年8月28日20:48:51 let convertToBase7 function (num) {if (num 0) {return 0}let res ;let isPositiveNum true;if (num < 0) {num -num;isPositiveNum false;}while (num ! 0) {let yushu num % 7;res yushu;num Math.floor(num / 7);}res res.split(…

vue 中通过监测滚动条加载数据(懒加载数据)

vue 中监测滚动条加载数据&#xff08;懒加载数据&#xff09; methods: {titleAlert(title) {console.log(title);alert(title)},// 获取滚动条当前的位置getScrollTop() {let scrollTop 0if (document.documentElement && document.documentElement.scrollTop) {sc…

字符串短横线和驼峰形式的互相转换 Javascript

// 短横线转换驼峰 function underline2Hump(str){let arr str.split(-); //["daaa", "df"] 或 ["", "daaa", "df"]for (let i 0; i < arr.length; i) {arr[i] arr[i].slice(0,1).toUpperCase()arr[i].slice(1)}retur…