前端常见重点问题解答,值得收藏~

74 阅读4分钟

1、eval与new Function的区别

(1)简介
eval和new Function都可以将一段字符串解析成一段JS脚本并执行。
(2)eval和 new Function的使用
① eval:

eval作为一个方法,直接传入要解析的字符串即可

const foo = "foo"; // 定义了一个变量foo
const str = "console.log(foo)";
eval(str); // 解析str字符串中包含JS脚本并执行,输出foo

② new Function:
JS中的每个函数都是 Function 类型的实例,即JS中所有的函数的proto都指向Function的prototype,或者说,JS中所有的函数都是由Function构造出来的

new Function() 可以接n个参数,最后一个参数作为函数体

let func = new Function ([arg1[, arg2[, ...argN]],] functionBody);
let foo = new Function("name", "console.log(name)");
// 创建的函数指向Function的原型
console.log(foo.__proto__ === Function.prototype); // true

// 等价于
function foo(name) {
    console.log(name);
}

可以看到Function的最后一个参数字符串"console.log(name)"也被解析成了JS脚本,并且作为函数体执行了

需要注意的是,传入的字符串不是任意的,必须是能当做JS脚本正常执行的字符串

const str = "{'foo': '123'}";
const obj = eval(str);
console.log(obj);
// 报错信息如下
VM1061:1 Uncaught SyntaxError: Unexpected token ':'
    at <anonymous>:2:18

因为传入"{'foo': foo}"的时候, {}会被解析为代码块,相当于直接执行const str = "'foo': foo";解决方法可以在外层加上一个括号,如:

const str = "({'foo': '123'})";
const obj = eval(str);
console.log(obj);// {foo: '123'}

eval和new Function的区别

eval中的代码执行时的作用域为当前作用域它可以访问到函数中的局部变量
new Function中的代码执行时的作用域为全局作用域不论它的在哪个地方调用的它访问的都是全局变量

let foo = "foo";
function bar() {
    let foo = "bar";
    eval("console.log(foo)"); // 输出bar
    new Function("console.log(foo)")(); // 输出foo
}
bar();

从输出结果可以看出,new Function访问到的始终是全局作用域中的变量;eval访问到的则是当前作用域中的变量
当然如果使用的是window.eval() 或者global.eval() 那么访问到的也始终是全局作用域中的变量

let foo = "foo";
function bar() {
    let foo = "bar";
    window.eval("console.log(foo)"); // 输出foo
    new Function("console.log(foo)")(); // 输出foo
}
bar();

此时输出都是foo了
如果全局作用域中没有指定的变量,那么将会报错,提示该变量没有定义

function bar() {
    let foo = "bar";
    window.eval("console.log(foo)"); // 报错
    new Function("console.log(foo)")(); // 报错
}
bar();
// 报错信息如下
VM1051:1 Uncaught ReferenceError: foo is not defined
    at eval (eval at bar ((index):3), <anonymous>:1:13)
    at eval (<anonymous>)
    at bar (<anonymous>:3:12)
    at <anonymous>:6:1

【VUE】Unterminated template literal:拼接字符串包括<script></script>时报错误

vue拼接字符串包括script标签时报错误提示Unterminated template literal解决方法加反斜杠就可以,在script结束标签里边加反斜杠</script>

2、前端 JS 项目代码如何实现循环 Nodelist Dom 列表?

在前端 JS 项目中,可以使用循环遍历 NodeList Dom 列表的方式有多种。以下是其中两种常见的方式:

  1. for 循环

使用 for 循环可以遍历 NodeList Dom 列表,代码示例如下:

const nodeList = document.querySelectorAll('.node-list');
for (let i = 0; i < nodeList.length; i++) {
  console.log(nodeList[i]);
}
  1. forEach 方法

使用 forEach 方法也可以遍历 NodeList Dom 列表,代码示例如下:

const nodeList = document.querySelectorAll('.node-list');
nodeList.forEach((node) => {
  console.log(node);
});

需要注意的是,NodeList 对象是一个类数组对象,不支持数组的所有方法,如 push、pop 等。如果需要将 NodeList 转换成数组,可以使用 Array.from 或者扩展运算符等方式进行转换,代码示例如下:

// 使用 Array.from 进行转换
const nodeList = document.querySelectorAll('.node-list');
const nodeListArray = Array.from(nodeList);

// 使用扩展运算符进行转换
const nodeList = document.querySelectorAll('.node-list');
const nodeListArray = [...nodeList];

疑惑: DOM 操作,我注意到当我使用 document.querySelectorAll 创建 NodeList 时,我可以使用 ForEach 循环。那应该是不可能的。为什么它有效?它只适用于数组。
这取决于浏览器,它在 chrome 中支持,但在其他浏览器中不支持。 NodeList 在其 chrome 原型(prototype)中有 forEach,但在其他浏览器中没有。

3、export {default as} from 【深入解读】

拆分前

export {default as b} from './table.js'

拆分后

import {default as b} from './table.js'
export b

export+import(先导入后导出)

// Table.js
export var table='我的表格'
----------------------------
// utils.js
// => import {table as Etable} from './Table.js'(1)
// => export Etable(2)
export { table as Etable } from './Table.js'//(1)+(2)= (3)
----------------------------
import (导入上面的moduleimport {Etable} from './utils.js'