Javascript基础知识(二)流程控制,函数

43 阅读7分钟

1:流程控制语句

(1) 条件语句

let score = 85;
if (score >= 90) {
  console.log("优秀");
} else if (score >= 60) {
  console.log("及格");
} else {
  console.log("不及格");
}

三元运算符:

let res = score >= 60 ? '合格' : '不合格';


(2) 循环语句

1.for循环语句

for (let i = 0; i < 5; i++) {
  console.log(i);
}

2.whlie循环语句

let j = 0;
while (j < 5) {
  console.log(j);
  j++;
}

3.do whlie循环语句

do while 要先进入do 先执行一次do里的函数 在进行while循环,所以不管while是什么条件都会先执行一次循环体

let start=0;
do{
  let n=0;
  let line = "";  // 创建一个空字符串来存储当前行的星号
  do{
    line += "*";  // 将星号添加到字符串中
  }while(++n<=start)
  console.log(line);  // 打印完整的行
}while(++start<=5)

4.break continue label循环机制语句

  • break 跳出循环

  • continue 跳出当前循环进入下次循环

  • lable语句(在开发中应该避免使用lable标签)

    • 基本语法

      labelName: statement
      

    • 主要用途
      跳出嵌套循环:可以直接跳出指定的外层循环
      继续指定循环:可以跳过指定循环的当前迭代

    • outerLoop: 
      for(let i = 0; i < 3; i++) {
        innerLoop:
        for(let j = 0; j < 3; j++) {
          console.log(`i=${i}, j=${j}`);
          if(i === 1 && j === 1) {
            break outerLoop; // 直接跳出外层循环
          }
        }
      }
      // 输出:
      // i=0, j=0
      // i=0, j=1
      // i=0, j=2
      // i=1, j=0
      // i=1, j=1
      


2:函数与作用域

(1) 函数声明与调用

函数声明:

function add(a, b) {
  return a + b;
}
console.log(add(2, 3)); // 5

函数表达式:

const sub = function(a, b) {
  return a - b;
}

箭头函数:

const mul = (a, b) => a * b;

匿名函数与立即执行函数:

//1.函数表达式
let fn = function () {
  document.write(`我是函数表达式`)
}
//2.调用函数只能在函数表达式的下方
fn()

//具名函数调用可以在任何位置
fun()
function fun() {
  document.write(`我是函数表达式`)
}

//立即执行函数必须加分号
let num = 10
  (function () { let num = 20 })();//小括号本质就是调用函数
(function () { let num = 10 })();


(2) 函数的作用域

console.log(a); // undefined(变量提升)
var a = 10;

// let / const 不存在提升(暂时性死区)
console.log(b); // ❌ 报错
let b = 20;

(3) 函数提升现象

函数提升:

函数在声明之前就可以被调用,会把所偶函数声明提升到当前作用域的最前端 只有函数会提升 但是函数表达式不会提升(var a=function --> 函数表达式)

 //函数在声明之前就可以被调用,会把所有函数声明提升到当前作用域的最前面
fn()
function fn(){
  console.log(Text);
}
//这样变量提升的是var fun 但是fun并不是函数 
fun()
var fun=function(){
  console.log(1)
}
//会报错 必须声明赋值后再调用

(4) 函数的动态参数与剩余参数

(1)动态参数

1.伪数组(Array-like): 了解动态参数先必须知道伪数组 伪数组形似数组可以通过索引来访问元素 但是不是一个数组 只拥有一个length属性 不具备数组的各种方法.

2.动态参数: 参数的数量可变 比如求和函数可以输入任意数量参数求和 这些输入的数会被存放在函数内部里面的argument伪数组变量中

 function getSum(){
      console.log(arguments);//动态参数 只存在函数里面 是一个伪数组
      let sum=0
      for(let i=0;i<arguments.length;i++){
        sum+=arguments[i]
      }
      return sum;
    }
  console.log(getSum(1,2,43,5,6,6)) // 63

(2)剩余参数

1.展开运算符: 首先需要了解展开运算法 ‘’…‘’ 一般可以展开数组或是对象

2.剩余参数: 剩余参数允许我们将一个不定数量的参数表示为一个数组

function getSum2 (...arr){//...的意思就是展开数组
  let sum=0
  for(let i=0;i<arr.length;i++){
    sum+=arr[i]
  }
  return sum
}
console.log(getSum2(1,2,43,5,6,6))//63

建议:在开发中我们图片使用剩余参数 因为在箭头函数中已经将伪数组函数内置变量删除了 而剩余数组使用的使用真正的数组变量(Array)

(5)函数的this指向问题

1. 普通函数中的 this

普通函数中的 this 指向取决于函数的调用方式,而不是定义方式。

function normalFunc() {
    console.log(this);
} 
normalFunc();
// 非严格模式下指向 window,严格模式下是 undefined window.normalFunc();
// 指向 window document.onclick = normalFunc; // 点击时 this 指向 document

总结:

  • 谁调用函数,this 就指向谁。
  • 默认情况下(非严格模式),指向全局对象 window

2. 对象方法中的 this

当函数作为对象的方法被调用时,this 指向该对象本身

const obj = {
    name: '测试对象',
    method: function () {
        console.log(this.name); // 输出 "测试对象"    
    } 
}; 
obj.method(); // this 指向 obj

总结:

  • 方法调用时,this 指向调用该方法的对象。

3. 箭头函数中的 this

箭头函数不创建自己的 this,它会继承外层作用域的 this

const fn = () => {
    console.log(this); // window(因为 fn 定义在全局作用域)
};

对象中的箭头函数:

const obj = {
    uname: 'aaa',
    sayHi: () => {
        console.log(this); // window(箭头函数没有自己的 this)
    }
};
obj.sayHi();

箭头函数嵌套在普通函数中:

const obj = {
    uname: 'aaa',
    sayHi: function () {
        const who = () => {
            console.log(this); // obj(箭头函数继承 sayHi 的 this)
        };
        who();
    }
};
obj.sayHi();

总结:

  • 箭头函数不绑定 this,它会从作用域链中继承 this
  • 在对象方法中使用箭头函数时要特别小心,它不会指向对象本身。

4. DOM 事件中的 this

在 DOM 事件处理函数中,this 默认指向触发事件的元素

document.querySelector('button').onclick = function () {
	console.log(this); // 指向 button 元素
   };

注意:

  • 如果使用箭头函数绑定事件,this 不会指向触发元素,而是继承外层作用域的 this
document.querySelector('button').onclick = () => {
console.log(this); // window(箭头函数继承全局作用域)
};


5. 构造函数中的 this

在构造函数中,this 指向新创建的实例对象

示例:

javascript

function Person(name) {
this.name = name;
console.log(this); // 指向新创建的实例
}
const person1 = new Person('Alice');

建议:

  • 避免在对象方法中使用箭头函数,除非你明确知道它会继承外层的 this
  • 在 DOM 事件中,优先使用普通函数以正确获取触发元素。
  • 使用 bind()call()apply() 可以手动指定 this 指向。

6. 改变this的指向

  1. call()
  • 语法function.call(thisArg, arg1, arg2, ...)
  • 特点:立即调用函数,同时改变函数中 this 的指向
  • 参数:第一个参数是 this 指向的对象,后续参数逐个传递
  1. apply()
  • 语法function.apply(thisArg, [argsArray])
  • 特点:立即调用函数,同时改变函数中 this 的指向
  • 参数:第一个参数是 this 指向的对象,第二个参数是数组(包含所有参数)
  1. bind()
  • 语法function.bind(thisArg, arg1, arg2, ...)
  • 特点:不立即调用函数,而是返回一个新函数,新函数中的 this 被永久绑定到指定对象
  • 参数:第一个参数是 this 指向的对象,后续参数会作为新函数的预设参数

核心区别

  • call 和 apply 都会立即执行函数,而 bind 返回一个新函数不立即执行
  • call 逐个传递参数,apply 通过数组传递参数,bind 可以预设参数