JS立即执行函数、逗号操作符

81 阅读2分钟

JS立即执行函数、逗号操作符

目录

立即执行函数

逗号操作符

一、立即执行函数

  • 立即执行函数又叫初始化函数
  • 当一个全局函数被声明后,这个函数会一直存在GO里,随时要用都能直接用
  • 如果一个函数只执行一次,那全局函数会浪费性能,所以需要立即执行函数

立即执行函数特点

  • 立即执行函数满足:

    1. 自动执行
    2. 执行完后立即销毁
 (function () {}()); // W3C建议写法
 ​
 (function () {})(); // 也能这样写
 ​
 !function() {}(); // 这样也行
  • 把函数变成表达式,后面加个括号(函数执行符号)才是完整的立即执行函数
  • 这里函数外的括号就是把函数变成了表达式
  • 立即执行函数前后必须确保有分号,否则会运算
 // 立即执行函数小例子
 ​
 (function () {
   var a = 1,
       b = 2;
   console.log(a + b);
 })(); // 3
 // 可以保存立即执行函数的返回值
 ​
 let num = (function (a, b) {
   return a + b;
 })(2, 4);
 console.log(num);
 //表达式才能被执行符号执行
 ​
 (function test1() {
   console.log(1); // 1
 })();
 ​
 ​
 let test2 = (function () {
   console.log(2); // 2
 })();
 ​
 ​
 function test3(){
   console.log(3); 报错
 }();
 ​
 function test(a, b) {
   console.log(1);
 }(6,5)
 6, 5; // 函数不执行也不会被报错 括号里有东西JS就会认为是一个表达式而不是函数的执行符号

二、逗号操作符

例子

 // 逗号表达式
 let num = (2 - 1, 6 + 5);
 console.log(num); // 11  num只返回逗号之后的表达式或值

面试题1

 // 面试题 页面上会出现什么数字
 ​
 function test() {
   var arr = [];
   for (var i = 0; i < 10; i++) {
     arr[i] = function () {
       // 每一次在给arr[i]赋值时只是把匿名函数放进去,但没有执行
       document.write(i + "");
     };
   }
   return arr; // 返回给外面的变量导致这10个匿名函数形成了10个闭包
 }
 var myArr = test(); // 此时test的AO和test切断但这10个匿名函数还抓着test的AO
 for (var j = 0; j < 10; j++) {
   myArr[j](); // 每一次执行时都会访问test的AO 此时的i就是10
 }
 // 打印10个10

面试1延伸

 // 面试题延伸,如果想打印0-9 
 // 最常用的 让循环里的函数变成立即执行函数 每次执行的就是i
 ​
 function test() {
   for (var i = 0; i < 10; i++) {
     (function () {
       document.write(i + " ");
     })(); // 页面上出现0-9
   }
 }
 test();

面试题2

 // 面试题2
 ​
 var fn = (function test1() {
   return 1;
 },
 function test2() {
   return "2";
 })();
 console.log(typeof fn);
 ​
 // 打印的是string 因为逗号运算符只返回逗号后的东西 函数fn只返回第二个test2的返回值 字符串2

面试题3

// 阿里面试题

var a = 10;
if (function b() {}) { // 函数声明不是false值 所以if能通过
  a += typeof b; //因为if后面的括号让function b(){}变成表达式了,表达式内函数名没有意义,所以找不到b,所以b是undefined
}
console.log(a); // typeof 检查后返回的是字符串类型的undefined 所以10 + 'undefined' = '10undefined'

面试题4

// 有五个li 点击五个li打印其对应0-5的数字
let oLi = document.querySelectorAll("li");
for (var i = 0; i < oLi.length; i++) {
  oLi[i].onclick = function () {
    console.log(i);
  };
}
//这样点击每一个li打印都是5 因为给每一个li循环赋值时只是绑定函数,当点击li才执行函数,执行函数时的i就等于5 所以每一次点击都等于5


//要达到预期效果
for (var i = 0; i < oLi.length; i++) {
  (function (j) {
    oLi[j].onclick = function () {
      console.log(j);
    };
  })(i);

三、课后作业

作业1

// 累加器 0 写个闭包
// 执行一次函数 加1
let showAdd = document.querySelector("#showAdd");
let btnAdd = document.querySelector("#btnAdd");
let btnClear = document.querySelector("#btnClear");
let n = 0;
function render(num) {
  showAdd.innerHTML = `当前数字是${num || 0}`;
}
render();
function add() {
  n += 1;
  return n;
}
btnAdd.addEventListener("click", () => {
  render(add());
});
btnClear.addEventListener("click", () => {
  n = 0;
  render(n);
});

作业2

// 缓存器 一个班级,学生名字保存在数组里,两个方法写在函数中的一个对象中,第一个方法是加入班级,第二个方法是离开班级。
// 每次加入或离开,都需要打印新的学生名单

function gather(name) {
  let className = [];
  let operation = {
    add: function (name) {
      className.push(name);
      console.log(className);
    },
    remove: function (name) {
      let index = className.indexOf(name);
      if (index < 0) {
        console.log("删除失败,请确认删除名字是否存在 %o", className);
      } else {
        className.splice(index, 1);
        console.log("删除成功 %o,", name, "已被删除", className);
      }
    },
  };
  return operation; //返回一个对象
}
let team = gather();

\