JS数据类型可以分为基本数据类型和引用数据类型。
其中基本数据类型包括:字符串(string)、数字(number)、布尔值(boolean)、空(null)、未定义(undefined),symbol(符号) 而引用数据类型则包括:对象(Object)
区别在于存储方式和赋值方式。基本数据类型的值直接存储在变量内,存在栈中,而引用数据类型的值存储的是该对象的内存地址。存在堆中
全局作用域:指的是定义在代码块外部、函数外部或者是模块外部的变量、函数等,它们拥有全局作用域。
局部作用域:指的是定义在代码块、函数或者是模块内部的变量、函数等,它们拥有局部作用域。
在ES6规范下,还引入了块级作用域的概念。块级作用域可以用花括号包裹一段代码,在这段代码内部定义的变量仅在此代码块内部有效,超出此范围后便会失效,不会影响其他代码块中的同名变量。
浅拷贝:将对象的引用复制给一个新对象,新对象和原对象引用的是同一个对象,修改一个对象的属性会影响另一个对象的属性。常见的浅拷贝方法有Object.assign()、扩展运算符(...)等。
深拷贝:将对象完全复制一份,新对象和原对象是两个独立的对象,修改一个对象的属性不会影响另一个对象的属性。常见的深拷贝方法有递归拷贝、JSON.parse(JSON.stringify())等。
以下是使用递归拷贝实现深拷贝的示例代码:
function deepCopy(source) { if (typeof source !== 'object' || source === null) { return source; } const target = Array.isArray(source) ? [] : {}; for (const key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = deepCopy(source[key]); } } return target; }
只要是对象的独有属性和方法,就应该定义在对象本身上
而对于一些多个对象需要共享的属性和方法,可以将它们定义在对象的原型(prototype)对象上。这样,多个对象就可以共享这些属性和方法,无需在每个对象上都定义一遍
一般来说,满足以下两点之一的属性或方法,应该定义在对象的原型对象上:
可以使用instanceof运算符来判断一个对象是否为某个构造函数的实例obj instanceof Object
this是一个特殊的关键字,它指向函数当前被调用时的上下文对象。this的具体指向取决于函数的调用方式。
function sayHello() { console.log(`Hello, my name is ${this.name}.`); } const obj = { name: 'jack' }; sayHello.call(obj); // Hello, my name is jack.
function sayHello() { console.log(`Hello, my name is ${this.name}.`); } const obj = { name: 'jack' }; const newFunc = sayHello.bind(obj); newFunc(); // Hello, my name is jack.
原型:每个函数都有一个 prototype(原型) 属性,这个属性是一个指针,指向一个对象,而这个对象包含某种特定类型的所有实例共享的属性和方法。
JavaScript 中所有的对象都是由它的原型对象继承而来。而原型对象自身也是一个对象,它也有自己的原型对象,这样层层上溯,就形成了一个类似链表的结构,这就是原型链
原型链是由原型对象组成的层次结构,它描述了JavaScript对象之间的继承关系。每个JavaScript对象的原型都指向它的继承原型,形成了一条链,即原型链。
原型链的终点是Object.prototype
。所有对象的原型链都是从Object.prototype
继承而来。如果在查找属性或方法时,最终到达了Object.prototype
,还是没有找到,则返回undefined。
Function.prototype
指向函数的原型对象。
异步编程是一种处理非阻塞I/O操作的技术,允许程序在某些操作执行的同时,执行其他操作,而不是等待这些操作执行完毕后才进行其他操作。
JavaScript中的异步编程可以通过回调函数、Promise、async/await、Generator函数等方式实现。
Promise 是异步编程的一种解决方案
承诺过一段时间会给你一个结果。promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
Promise是一种非常实用的异步编程技术,可以帮助我们更加优雅和高效地编写异步代码,避免多层回调函数嵌套的问题。
Promise实例可以通过.then()方法链式调用多个回调函数,每个回调函数可以处理前一个回调函数的返回值,即通过return语句将值传递给下一个回调函数。
promise.then(function(value1) { // 处理 value1,并返回 value2 return value2; }).then(function(value2) { // 处理 value2,并返回 value3 return value3; }).then(function(value3) { // 处理 value3 });
Promise中的值是通过Promise的链式调用不断传递的,每个.then()方法的返回值可以作为下一个.then()方法执行的参数,从而实现值的传递和处理。
可以使用 try/catch
语句来捕捉异步操作中的异常
async function fetchData() { try { const response = await fetch('/api/data'); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } }
async/await的底层原理是基于ES6中引入的Generator函数和Promise对象实现的。
Generator函数可以通过function*关键字定义,它返回一个可迭代对象,可以通过.next()方法一步一步执行函数中的代码,每次执行到yield语句时,函数暂停并返回一个yield表达式的值。可以通过.next()方法恢复函数执行并传递参数。例如:
1xx:信息性状态码
2xx:成功状态码
4xx:客户端错误状态码
5xx:服务器错误状态码
协商缓存指的是客户端缓存中保存了一个资源的元数据; 当客户端发起请求时,会与服务器进行一次“协商”,如果服务器端判断该资源自上次请求后并未发生改变,服务器会返回 304 Not Modified,告诉客户端可以继续使用缓存中的资源,从而避免了不必要的数据传输,减轻了服务器的负担,提高了网页加载速度。
协商缓存的过程如下:
协商缓存存在客户端和服务器端,客户端通过浏览器缓存将资源保存在本地,避免再次发送请求;在服务器端,通过响应头的 Last-Modified 和 If-Modified-Since 字段进行通信,减少不必要的网络请求和数据传输。
cookie常用的属性有以下几种:
Vue3 引入了组合式 API,替代 Vue2 的选项式 API,它使得组件的逻辑更清晰、更易于测试和组合。
vue2 的响应性主要依赖 Object.defineProperty 进行实现,但是 Object.defineProperty 只能监听 指定对象的指定属性的 getter 行为和 setter 行为;我们在 data 中声明了一个对象 person ,但是在后期为 person 增加了新的属性,那么这个新的属性就会失去响应性。想要解决这个问题其实也非常的简单,可以通过 Vue.$set 方法来增加 指定对象指定属性的响应性。但是这样的一种方式,在 Vue 的自动响应性机制中是不合理。
在 Vue3 中,Vue 引入了反射和代理的概念,所谓反射指的是 Reflect,所谓代理指的是 Proxy。我们可以利用 Proxy 直接代理一个普通对象,得到一个 proxy 实例 的代理对象。在 vue3 中,这个过程通过 reactive 这个方法进行实现。
Object.defineProperty 可以用于监听对象属性的变化,但是不能直接监听数组的变化。
如果要监听到数组的变化,可以使用 Array.prototype 提供的一些方法,比如 push、pop、splice 等; 使用 Vue 提供的 Vue.set 或 $set 方法来实现数组响应式。
因为 Object.defineProperty 在监听一个对象的变化时,实际上是监听到了对象的某个属性的变化。而对于数组来说,它的某些操作(如 push、pop、splice 等)实际上是修改了数组本身的属性,而不是修改了某个已存在的属性的值。
组件是一个可复用的实例,当你引用一个组件的时候,组件里的data是一个普通的对象,所有用到这个组件的都引用的同一个data,就会造成数据污染。
将data封装成函数后,在实例化组件的时候,我们只是调用了data函数生成的数据副本,避免了数据污染。
Vue 在初始化时会检测组件实例对象上所有声明的属性,将这些属性添加到 Vue 的响应式系统中。而在组件实例对象上直接声明属性,这些属性不会被添加到响应式系统中,也就不具有响应式的能力。
可以使用 <router-link>
标签或 router.push
方法来跳转到对应的页面。
引入vue-router
库来定义路由,包括路由的路径和对应的组件
Vuex(Vue.js 中央状态管理模式)是一个专为 Vue.js 应用程序开发的状态管理库。它采用集中式存储管理全局共享状态,可以让我们更好地组织、维护和管理 Vue.js 应用程序中的状态。
Vuex 的核心概念分为以下几个部分:
Vue 组件间通信有以下几种方式:
React 组件间通信也有以下几种方式:
git init :将当前目录初始化为Git仓库 git add <file> :将文件添加到本地暂存区 git commit -m "message" :将暂存区的文件提交到本地仓库,并添加操作说明message git push :将本地仓库内容推送到远程仓库 git pull :将远程仓库内容拉取到本地仓库 git clone :克隆远程仓库到本地
当需要回滚(即撤销)操作时,可以通过以下命令实现:
git reset:将文件从stage(即暂存区)中撤回到unstage(即工作区)
git reset --soft: 撤回commit,但不影响stage和工作区,可以使用git status查看变化 git reset --mixed: 撤回commit和stage,但不影响工作区,可以使用git status查看变化 git reset --hard: 撤回commit、stage和工作区,本地所有修改都会被删除,请谨慎使用
git revert:将指定commit的修改撤回(即创建一个新的commit来覆盖原有commit的修改)
git revert <commit-hash>: 撤回commit-hash对应的commit
Webpack是一个现代化的静态模块打包器,它将各种不同类型的文件(如js、css、图片等)视为一个模块,并将它们打包成最终的静态资源。Webpack的核心原理是将所有的资源都视为一个模块,并通过loader进行转换处理,最后将这些模块打包成一个或多个bundle。
Webpack的主要作用是优化前端资源加载,将多个文件打包成一个压缩文件,使得网页加载速度更快,用户体验更好。同时,Webpack还支持开发模式和生产模式的切换,支持开发过程中自动编译和热更新,以及支持代码分割和懒加载等高级特性,使得前端开发更加便捷和高效。
其他常用的插件有:
Webpack可以处理各种类型的文件,例如JavaScript、CSS、HTML、图片、字体等资源。Webpack通过使用loader来转译这些文件,将其转换为Webpack可以处理的模块。
Webpack可以处理大部分前端开发中遇到的文件类型。但是对于一些特殊的文件类型,例如PDF和Word文档等非常规的文件类型,Webpack可能并不能直接处理,需要借助其他工具或loader来进行支持。
可以使用双指针的方法解决,左指针指向已处理好的序列的尾部,右指针指向待处理序列的头部。遍历数组,当右指针指向的元素为0时,右指针向右移动1位,否则交换左右指针所指向的元素,左右指针同时向右移动1位。
function moveZeroes(nums) { let left = 0, right = 0; while (right < nums.length) { if (nums[right] !== 0) { // 交换左右指针所指向的元素 let temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; // 左右指针同时向右移动1位 left++; } // 右指针向右移动1位 right++; } return nums; }#大家都开始春招面试了吗##春招##前端面试##面试答案##美团#