无经验计科应届生前端面试遇到的问题整理

js数据类型有几种,分别是

原始数据类型(Primitive data types):
字符串(String): 用于表示文本数据,使用单引号(‘’)或双引号(“”)括起来。
数字(Number): 用于表示数值数据,包括整数和浮点数。
布尔值(Boolean): 用于表示逻辑值,true(真)或false(假)。
空值(Null): 表示一个空值或没有值。
未定义(Undefined): 表示一个未初始化的值或不存在的值。
Symbol:表示唯一的标识符。
复合数据类型(Composite data types):
对象(Object): 用于表示复杂的数据结构,可以包含多个键值对。
数组(Array): 用于表示按顺序排列的值的集合,每个值都有一个索引。
函数(Function): 用于封装可执行代码块。
特殊数据类型:
BigInt: 用于表示任意精度的整数。
Promise: 用于表示一个异步操作的最终结果。
原始包装类型(Primitive wrapper objects):用于将原始数据类型包装成对象,如String、Number和Boolean。

请简要谈谈你对js原型链的理解

JavaScript原型链是一种重要的概念,它是JavaScript中实现继承的机制之一。理解原型链对于理解JavaScript的对象和继承非常重要。

在JavaScript中,每个对象都有一个原型(prototype),它是一个指向另一个对象的引用。这个被指向的对象就是原型对象,它包含了共享的属性和方法。当你访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript会沿着原型链去查找,直到找到该属性或方法或者到达原型链的末端(即Object.prototype)。

原型链的形成是基于对象之间的关系。每个对象都有一个[[Prototype]]内部属性,它指向该对象的原型。通过这种方式,JavaScript实现了对象之间的继承关系。如果你试图访问一个对象的属性或方法,JavaScript引擎会首先检查该对象本身是否有该属性或方法,如果没有,它会沿着原型链向上查找,直到找到为止。

JavaScript的原型链形成如下图所示
在这里插入图片描述
在上面的示例中,Object是所有JavaScript对象的顶层原型,Constructor是构造函数的原型,Prototype是构造函数实例的原型。沿着原型链,可以通过继承的方式访问到Object、Constructor和Prototype中定义的属性和方法。

原型链的概念使得JavaScript的对象可以实现继承。

js中的类型是什么

JavaScript中的类型可以分为两大类:原始类型(Primitive types)和对象类型(Object types)。

原始类型(Primitive types):
字符串(String): 表示文本数据,用于存储字符序列。
数字(Number): 表示数值数据,包括整数和浮点数。
布尔值(Boolean): 表示逻辑值,true或false。
空值(Null): 表示一个空值或没有值。
未定义(Undefined): 表示一个未初始化的值或不存在的值。
Symbol: 表示唯一的标识符。
对象类型(Object types):
对象(Object): 用于表示复杂的数据结构,可以包含多个键值对。
数组(Array): 用于表示按顺序排列的值的集合,每个值都有一个索引。
函数(Function): 用于封装可执行代码块。
日期(Date): 用于表示日期和时间。
正则表达式(RegExp): 用于匹配字符串的模式。
JavaScript的类型系统是动态的,这意味着变量的类型是在运行时确定的,而不是在编译时确定的。此外,JavaScript是一种弱类型语言,允许不同类型之间的自动类型转换。

你是怎样理解闭包的

闭包(Closure)是指在函数内部创建另一个函数时,内部函数可以访问外部函数作用域中的变量,并且保持对这些变量的引用,即使外部函数已经执行完毕,这种现象被称为闭包。换句话说,闭包是函数和其相关的引用环境的组合。

闭包通常发生在嵌套函数中,内部函数可以访问外部函数的局部变量、参数以及其它内部函数,即使外部函数已经执行完毕,这些变量依然可以被内部函数访问和操作。

function outerFunction() {
    var outerVariable = 'I am outer!';

    function innerFunction() {
        console.log(outerVariable); // 内部函数可以访问外部函数的变量
    }

    return innerFunction;
}

var innerFunc = outerFunction(); // 调用外部函数,返回内部函数
innerFunc(); // 调用内部函数,打印 'I am outer!'

在上面的例子中,内部函数innerFunction可以访问外部函数outerFunction中声明的变量outerVariable,即使outerFunction已经执行完毕,innerFunction仍然可以访问和操作outerVariable,这就是闭包的作用。

js数组中对象的类型可以是

在JavaScript中,数组中可以存储各种类型的对象,包括但不限于:
普通对象(Plain Objects):即由花括号 {} 创建的对象,用于存储键值对的集合。

var person = { name: "John", age: 30 };
var car = { make: "Toyota", model: "Camry" };

var objectsArray = [person, car];

自定义对象:使用构造函数或类创建的对象。

function Animal(name) {
    this.name = name;
}

var dog = new Animal("Rex");
var cat = new Animal("Whiskers");

var animalsArray = [dog, cat];

数组对象(Array Objects):数组中可以存储其他数组。

var array1 = [1, 2, 3];
var array2 = ["a", "b", "c"];

var arraysArray = [array1, array2];

函数对象(Function Objects):数组中可以存储函数。

function greet(name) {
    console.log("Hello, " + name + "!");
}

var functionsArray = [greet];

其他类型的对象:比如日期对象、正则表达式对象等。

var date = new Date();
var regex = /[a-z]/;

var otherObjectsArray = [date, regex];

ES6中的新特性是什么

箭头函数(Arrow Functions):提供了一种更简洁的函数定义语法,并且绑定了词法作用域。

// ES5
function add(a, b) {
    return a + b;
}

// ES6
const add = (a, b) => a + b;

模板字符串(Template Literals):可以通过 ${} 插入表达式,更方便地构建多行字符串和字符串插值。

// ES5
var name = "Alice";
console.log("Hello, " + name + "!");

// ES6
const name = "Alice";
console.log(`Hello, ${name}!`);

解构赋值(Destructuring Assignment):可以从数组或对象中提取值,然后将其赋值给变量。

// ES5
var arr = [1, 2, 3];
var a = arr[0];
var b = arr[1];

// ES6
const arr = [1, 2, 3];
const [a, b] = arr;

默认参数(Default Parameters):可以在函数声明时为参数设置默认值。

// ES5
function greet(name) {
    name = name || 'Guest';
    console.log('Hello, ' + name + '!');
}

// ES6
function greet(name = 'Guest') {
    console.log(`Hello, ${name}!`);
}

展开运算符(Spread Operator):用于在函数调用或数组字面量中展开数组、对象或字符串。

// ES6
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const mergedArray = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

类(Class):引入了类的概念,更符合传统面向对象编程的思维方式。

// ES6
class Person {
    constructor(name) {
        this.name = name;
    }

    greet() {
        console.log(`Hello, ${this.name}!`);
    }
}

const person = new Person('Alice');
person.greet(); // "Hello, Alice!"

模块化(Modules):引入了模块化的概念,允许将代码分割为多个文件,并使用 import 和 export 来导入和导出模块。

// math.js
export const sum = (a, b) => a + b;

// main.js
import { sum } from './math.js';
console.log(sum(1, 2)); // 3

迭代器(Iterators)和 for…of 循环:引入了统一的迭代器接口,使得对象可以被遍历,同时提供了 for…of 循环语法用于迭代。

// ES6
const arr = [1, 2, 3];
for (const item of arr) {
    console.log(item); // 1, 2, 3
}

Promise 对象:提供了一种处理异步操作的方式,避免了回调地狱(callback hell)。

// ES6
const promise = new Promise((resolve, reject) => {
    // 异步操作
    if (/* 操作成功 */) {
        resolve(result);
    } else {
        reject(error);
    }
});

promise.then(result => {
    // 成功处理
}).catch(error => {
    // 失败处理
});

Generators(生成器):可以通过函数的暂停和恢复来简化异步编程,使用 function* 定义生成器函数,并使用 yield 暂停生成器的执行。

// ES6
function* generatorFunction() {
    yield 1;
    yield 2;
    yield 3;
}

const generator = generatorFunction();
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
console.log(generator.next().value); // 3

Map 和 Set:引入了 Map 和 Set 数据结构,提供了更灵活的键值对集合和唯一值集合。

// ES6
const map = new Map();
map.set('key', 'value');
console.log(map.get('key')); // "value"

const set = new Set([1, 2, 3, 3, 4]);
console.log(set.size); // 4

Proxy 和 Reflect:引入了 Proxy 和 Reflect 对象,用于拦截和自定义对象的操作。

// ES6
const target = {};
const handler = {
    get(target, prop, receiver) {
        console.log(`Getting property "${prop}"`);
        return Reflect.get(target, prop, receiver);
    }
};
const proxy = new Proxy(target, handler);
proxy.foo; // 触发 get 拦截

众所周知2015年前是不存在前后端这个概念的,请谈谈你对现今前端工程概念的理解,或者说你认为前端工程是什么

前端工程是指涉及前端开发的一系列工程化实践和技术,旨在提高前端开发效率、代码质量和项目可维护性。以下是前端工程中一些重要的概念:

版本控制(Version Control):使用版本控制系统(如Git)来管理项目的代码,追踪代码的变更历史,并协作开发和解决代码冲突。
包管理器(Package Manager):使用包管理器(如npm、Yarn)来管理项目中使用的第三方库和工具,以及项目的依赖关系。
构建工具(Build Tools):使用构建工具(如Webpack、Parcel、Rollup)来将多个源文件打包成一个或多个静态资源文件,同时进行代码压缩、模块化处理、资源优化等。
模块化(Module Bundling):采用模块化的开发方式,将前端代码分割成多个模块,并使用工具将这些模块打包成一个或多个最终的部署文件。
预处理器和后处理器(Preprocessors and Postprocessors):使用预处理器(如Sass、Less)和后处理器(如PostCSS)来扩展CSS的功能,例如变量、混合、嵌套、自动前缀等。
代码规范和风格指南(Code Style and Guidelines):遵循统一的代码规范和风格指南,以提高代码的可读性、可维护性和一致性。
自动化测试(Automated Testing):编写单元测试、集成测试和端到端测试,并使用自动化测试工具(如Jest、Mocha、Cypress)进行自动化测试,以确保代码的质量和稳定性。
持续集成和持续部署(Continuous Integration and Continuous Deployment):使用持续集成(CI)和持续部署(CD)工具(如Travis CI、Jenkins、CircleCI)来自动化构建、测试和部署过程,以提高开发团队的效率和代码交付的速度。
性能优化(Performance Optimization):优化前端代码和资源加载性能,包括减少HTTP请求、压缩和缓存静态资源、使用CDN加速等。
安全性(Security):保护前端应用程序免受常见的安全漏洞和攻击,包括跨站脚本(XSS)、跨站请求伪造(CSRF)、点击劫持等。
代码分割(Code Splitting):将前端代码按照路由或功能进行分割,以减少首次加载时间和提高页面加载性能。
跨浏览器兼容性(Cross-Browser Compatibility):确保前端代码在不同浏览器和设备上具有良好的兼容性和表现。

vue2和vue3的区别

Vue.js 3 是 Vue.js 的下一个主要版本,与 Vue.js 2 相比,有许多重要的变化和改进。以下是 Vue.js 3 相对于 Vue.js 2 的一些主要区别:

性能优化:
Vue.js 3 使用了 Virtual DOM 的重写,提高了渲染性能和内存利用率。
引入了静态树提升(Static Tree Hoisting)和标记(Static Props Hoisting)等优化策略,进一步减少了虚拟 DOM 的创建和比较成本。
更小的体积:
Vue.js 3 的核心代码库经过了重构和优化,使得体积更小,加载更快。
Composition API:
Vue.js 3 引入了 Composition API,提供了一种新的组件组织形式,使得代码更具逻辑性和可维护性。
Composition API 允许将组件逻辑按照功能划分为多个函数,而不是强制按照生命周期钩子划分。
更好的 TypeScript 支持:
Vue.js 3 对 TypeScript 的支持更加完善,提供了更好的类型推断和代码提示。
更强大的响应式系统:
Vue.js 3 中的响应式系统经过了重构和优化,使得在不同场景下的性能更好。
引入了 Proxy 对象作为底层实现,取代了 Object.defineProperty,提供了更多的反应性能力和更好的性能。
组件和 API 的修改:
Vue.js 3 对一些组件和 API 进行了修改和调整,以提高一致性和可用性。
例如,删除了 o n 、 on、 onoff 和 $once 方法,使用全局事件总线时需要手动清理。
部分组件的生命周期钩子和配置选项发生了变化。
TypeScript 支持:
Vue.js 3 对 TypeScript 的支持更为深入和完善,提供了更好的类型推断和编译时的类型检查。
总的来说,Vue.js 3 在性能、体积、开发体验和可维护性等方面都有了显著的改进,是 Vue.js 的一次重要升级。

npm是什么

npm(Node Package Manager)是 Node.js 生态系统中的包管理工具,用于管理 JavaScript 项目中的依赖包、执行脚本、发布和共享代码等。npm 是 Node.js 的默认包管理工具,随着 Node.js 一起安装。

npm 允许开发者在自己的项目中方便地安装、更新和删除依赖包,并且可以通过命令行界面轻松地管理项目的依赖关系。除了管理项目的依赖关系之外,npm 还提供了许多其他功能,包括:

包管理:npm 允许开发者在自己的项目中安装、更新、卸载依赖包,以及查看依赖包的版本信息、依赖关系树等。
包发布:开发者可以将自己编写的代码打包成一个 npm 包,并发布到 npm 公共仓库或私有仓库中,供其他开发者使用。
命令行工具:npm 提供了丰富的命令行工具,用于执行脚本、查看项目信息、搜索依赖包、初始化项目等。
版本管理:npm 使用语义化版本规范(Semantic Versioning)管理依赖包的版本,开发者可以指定依赖包的版本范围,以确保项目的稳定性和兼容性。
脚本执行:npm 允许开发者在 package.json 文件中定义脚本命令,用于执行各种任务,如构建、测试、打包等。
依赖解析:npm 使用依赖解析算法来解决依赖包的版本冲突和循环依赖等问题,以确保项目的稳定性和可靠性。
生态系统:npm 是一个庞大的生态系统,拥有数量庞大的开源依赖包,开发者可以在 npm 上找到几乎任何类型的 JavaScript 包和工具。

webpack是什么

Webpack 是一个现代化的 JavaScript 应用程序的静态模块打包器(module bundler)。它主要用于处理 JavaScript 文件,但也可以处理许多其他资源,例如 CSS、图片等。Webpack 将应用程序视为一个由模块组成的图,其中每个模块都是一个文件。当 Webpack 处理应用程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将所有模块打包成一个或多个 bundle。

Webpack 的主要功能包括:

模块打包:Webpack 可以将各种类型的模块(包括 JavaScript、CSS、图片等)打包成静态资源文件,以便浏览器加载。
依赖管理:Webpack 可以分析项目中的依赖关系,并自动解决模块之间的依赖关系,将它们打包到最终的输出文件中。
代码拆分:Webpack 允许将代码拆分成多个 bundle,以实现按需加载和减少初始加载时间。
加载器(Loaders):Webpack 可以通过加载器转换非 JavaScript 模块,例如将 ES6+ 代码转换为 ES5、将 Sass 或 Less 转换为 CSS 等。
插件(Plugins):Webpack 可以通过插件执行各种任务,例如压缩代码、提取公共模块、生成 HTML 文件等。
开发服务器:Webpack 提供了开发服务器,可以在开发过程中实时监听文件变化并自动重新构建项目,以提高开发效率。

webpack.load 的原理

Webpack的loader机制是Webpack中的一个重要特性,它允许开发者在打包构建过程中对特定类型的文件进行转换和处理。加载器(loader)可以将不同类型的资源文件(如JavaScript模块、CSS、图片、字体等)转换为Webpack可以处理的模块。

下面是Webpack loader的基本原理:

配置规则:在Webpack配置文件中,开发者可以通过module.rules配置项定义加载器规则。每个规则由一个对象组成,包括test用于匹配文件路径的正则表达式,以及use用于指定使用的加载器。

加载器链:当Webpack构建过程中遇到需要加载的文件时,根据配置的规则,Webpack会根据文件路径匹配规则,确定需要使用的加载器。如果规则中有多个加载器,加载器会形成一个加载器链,按照从右到左的顺序依次执行。

加载器处理:每个加载器负责对文件进行转换和处理。Webpack将文件内容传递给加载器,加载器对内容进行处理,并将处理后的结果返回。处理过程可以包括编译、转换、压缩、优化等操作。

模块输出:最终,Webpack将加载器处理后的结果作为模块输出,将其加入到打包生成的bundle中。这样,Webpack就可以处理各种不同类型的资源文件,并将它们整合到最终的输出结果中。

使用箭头函数需要注意的地方

this的绑定:箭头函数的this值绑定到定义时的上下文,而不是调用时的上下文。这意味着箭头函数内部的this值不会随着函数的调用方式而改变,而是继承自外层作用域的this值。

const obj = {
    name: 'Alice',
    greet: function() {
        console.log(`Hello, ${this.name}!`);
    },
    greetArrow: () => {
        console.log(`Hello, ${this.name}!`);
    }
};

obj.greet(); // 输出:Hello, Alice!
obj.greetArrow(); // 输出:Hello, undefined!

什么叫外层作用域呢,即箭头函数所在对象之外的全局作用域,例子中全局作用域中没有name,所以返回undefined,但如果全局作用域中有name,则箭头函数会输出name值

不适用于构造函数:箭头函数不能用作构造函数,不能通过new关键字来调用,并且没有自己的prototype属性。如果尝试使用new关键字调用箭头函数,会抛出错误。

const Foo = () => {};
const fooInstance = new Foo(); // 报错:Foo is not a constructor

arguments对象:箭头函数不具有自己的arguments对象,它们会继承外层作用域的arguments对象。如果需要使用函数内部的参数列表,可以使用ES6的剩余参数(…args)来代替。

function example() {
    const arrowFunc = () => {
        console.log(arguments); // 继承自外层作用域的arguments对象
    };
    arrowFunc();
}

example(1, 2, 3); // 输出:[1, 2, 3]

没有自己的super关键字:箭头函数没有自己的super关键字,它们会继承外层作用域的super关键字。如果需要在子类中访问父类的方法或属性,应该使用普通函数而不是箭头函数。

class Parent {
    constructor() {
        this.name = 'Parent';
    }
}

class Child extends Parent {
    constructor() {
        super();
    }

    getNameArrow() {
        return () => {
            return super.name; // 继承自外层作用域的super关键字
        };
    }

    getNameRegular() {
        return function() {
            return super.name; // 正确访问父类的方法或属性
        };
    }
}

const child = new Child();
console.log(child.getNameArrow()()); // 输出:Parent
console.log(child.getNameRegular()()); // 输出:Parent

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值