JS面试基础(2) 流程控制语句与函数及其作用域
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=0for(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=0for(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的指向
- call()
- 语法:
function.call(thisArg, arg1, arg2, ...) - 特点:立即调用函数,同时改变函数中
this的指向 - 参数:第一个参数是
this指向的对象,后续参数逐个传递
- apply()
- 语法:
function.apply(thisArg, [argsArray]) - 特点:立即调用函数,同时改变函数中
this的指向 - 参数:第一个参数是
this指向的对象,第二个参数是数组(包含所有参数)
- bind()
- 语法:
function.bind(thisArg, arg1, arg2, ...) - 特点:不立即调用函数,而是返回一个新函数,新函数中的
this被永久绑定到指定对象 - 参数:第一个参数是
this指向的对象,后续参数会作为新函数的预设参数
核心区别:
call和apply都会立即执行函数,而bind返回一个新函数不立即执行call逐个传递参数,apply通过数组传递参数,bind可以预设参数
