js的基础问题

1.js有哪些内置对象(封装的构造函数)

数据封装类对象:Object,Array,Boolean,Number,String

其他对象:Function,Arguments,Math,Date,RegExp,Error

ES6新增对象:Symbol,Map,Set,Promises,Proxy,Reflect

2.如何最小化重绘和回流?

需要对元素进行复杂操作时,可以先隐藏(display:none;),操作完成后再显示

需要创建多个dom节点时,使用documentFrament创建完后一次性的加入document

缓存Layout的属性值,如:var left=elem.offsetLeft,多次使用left只产生一次回流

尽量避免用table布局,table元素一旦出发回流就会导致table里所有的元素回流

3.js的作用域链

全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节

如果当前作用域没有找到属性或方法,向上层作用域查找,直到全局函数,这种形式就是作用域链

4.数据请求

javascript 复制代码
// GET 请求示例
var xhrGet = new XMLHttpRequest();
xhrGet.open('GET', 'https://api.example.com/data', true);
xhrGet.onreadystatechange = function () {
    if (xhrGet.readyState === 4) {
        if (xhrGet.status === 200) {
            console.log('GET Response:', JSON.parse(xhrGet.responseText));
        } else {
            console.error('GET Error:', xhrGet.statusText);
        }
    }
};
xhrGet.send();


// POST 请求示例
var xhrPost = new XMLHttpRequest();
xhrPost.open('POST', 'https://api.example.com/data', true);
xhrPost.setRequestHeader('Content-Type', 'application/json');

xhrPost.onreadystatechange = function () {
    if (xhrPost.readyState === 4) {
        if (xhrPost.status === 200) {
            console.log('POST Response:', JSON.parse(xhrPost.responseText));
        } else {
            console.error('POST Error:', xhrPost.statusText);
        }
    }
};
var data = JSON.stringify({ name: 'John', age: 30 });
xhrPost.send(data);

5.跨域和同源策略

同源策略是浏览器的一种机制,只允许在同源,也就是同协议、域名、同端口的情况下才能进行数据交互。

跨域方式:

JSONP,主要依赖的是script标签不受同源策略影响,src指向某一个接口的地址,同步需要传递callback回调函数名字,这样当接调用成功后,本地创建的全局回调函数就会执行,并且接收到函数。

javascript 复制代码
服务端实现
const express = require('express');
const app = express();

app.get('/api/data', (req, res) => {
    const callback = req.query.callback; // 获取回调函数名
    const data = { message: 'Hello, JSONP!' }; // 要返回的数据

    // 将数据包装在回调函数中
    res.type('application/javascript');
    res.send(`${callback}(${JSON.stringify(data)})`);
});

app.listen(3000, () => {
    console.log('Server running on http://localhost:3000');
});

客户端实现
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSONP Example</title>
    <script>
        function handleResponse(data) {
            console.log(data.message); // 处理返回的数据
        }

        function fetchData() {
            const script = document.createElement('script');
            script.src = 'http://localhost:3000/api/data?callback=handleResponse'; 
            // 指定回调函数
            document.body.appendChild(script); // 将 script 标签添加到文档中
        }
    </script>
</head>
<body>
    <button onclick="fetchData()">Fetch Data</button>
</body>
</html>

缺点

  1. 只支持 GET 请求 :由于是通过 <script> 标签实现的,JSONP 只支持 GET 请求,无法发送 POST 请求。
  2. 安全性问题:JSONP 请求可能会带来 XSS(跨站脚本攻击)风险,因为它执行的是返回的 JavaScript 代码。
  3. 回调函数名称冲突:如果多个请求使用相同的回调函数名,可能会导致冲突。

cors,依赖服务器对前端的请求头信息进行放行,不做限制。

javascript 复制代码
在服务器端配置CORS
const express = require('express');
const cors = require('cors');
const app = express();

// 允许所有域名
app.use(cors());

// 或者配置特定的域名
app.use(cors({
    origin: 'http://example.com', // 允许访问的源
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', // 允许的方法
    credentials: true // 允许发送凭证
}));

app.get('/data', (req, res) => {
    res.json({ msg: 'This is CORS-enabled for an allowed origin.' });
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});
  • 服务器通过设置CORS相关的响应头来表明允许跨域请求:
    • Access-Control-Allow-Origin: 指定允许访问的源,可以是具体的域名,也可以是*(允许所有域名)。
    • Access-Control-Allow-Methods: 指定允许的HTTP方法(如GET, POST, OPTIONS等)。
    • Access-Control-Allow-Headers: 指定允许的自定义头部。
    • Access-Control-Allow-Credentials: 指定是否允许发送凭证(如Cookies)。
    • Access-Control-Max-Age: 指定预检请求的有效时间。

代理访问,前端访问不存在跨域问题的代理服务器,代理服务器再去访问目标服务器。服务器之间没有跨域限制。

6.面向对象

构造函数

是一个特殊类型的函数,用于创建对象。它通常以大写字母开头,以示区分。构造函数使用 new 关键字来实例化对象。

javascript 复制代码
function Test(name,age){
  this.name=name;
  this.age=age;
  this.getName=function(){
    return this.name
  }
}
var obj=new Test('xiaoming',18)
var obj2=new Test('xiaozhang',100)
原型

每个 JavaScript 对象都有一个原型属性(__proto__),该属性指向一个对象,该对象包含可以共享的属性和方法。使用原型的好处是可以减少内存的使用,因为所有实例共享同一原型中的方法。

定义原型方法

可以在构造函数的 prototype 属性上添加方法和属性:

javascript 复制代码
Person.prototype.sayHello = function() {
    console.log(`Hello, my name is ${this.name}`);
};
person1.sayHello(); // 输出: Hello, my name is Alice
通过原型继承

还可以使用原型实现继承。创建一个子构造函数并使其原型指向父构造函数的实例。

javascript 复制代码
function Student(name, age, grade) {
    Person.call(this, name, age); // 调用父构造函数
    this.grade = grade; // 学生特有的属性
}

// 继承 Person 的原型
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student; // 修正构造函数指向
Student.prototype.study = function() {
    console.log(`${this.name} is studying.`);
};

const student1 = new Student("Bob", 20, "A");
student1.sayHello(); // 输出: Hello, my name is Bob
student1.study();    // 输出: Bob is studying.
原型链

任何一个实例都可以通过原型链找到它上面的原型,该原型对象上的属性和方法,可以被所有的原型实例共享。

7.闭包

闭包是js中的一种特性,当A函数中返回了B函数,并且返回的B函数中有使用到A函数中的局部变量,就会形成一个特性的形态,就叫闭包。

节流(Throttle)

节流是一种控制函数在一定时间内只能执行一次的技术。它会确保函数在规定的时间间隔内只执行一次,即使事件被频繁触发。

防抖(Debounce)

防抖是一种限制函数在短时间内被频繁调用的技术。它会延迟执行函数,直到某个事件停止触发一段时间后才执行。

8.数组去重

9.数组合并方法

10.数组扁平化

11.线程和进程的区别

进程是资源分配的最小单元。线程是代码执行的最小单元。

一个应用程序可能开启多个进程,进程之间数据不共享,一个进程内部可以开启多个线程,线程之间的数据是可以共享的,所以多线程的情况下,往往是要考虑线程间的执行顺序问题。

浏览器其实可以通过webworkers开启多个线程。

12.协商缓存和强缓存的区别

协商缓存和强缓存指的都是浏览器对静态资源文件的缓存机制。描述的就是什么时候去服务器请求,什么时候直接读取缓存中的文件

强缓存

是客户端直接查看本地的缓存文件是否过期,如果没有过期就直接取用。

查看过期的方法主要是依赖响应头上的expirce绝对时间和cache-control相对时间来对比的

协商缓存

指的是客户端去访问服务器对应的文件是否有更新,如果有更新才会重新请求

依靠的是响应头上的last-modified最后更新时间及etag内容变更的标示来确认文件是否有更新。

一个文件是否重新请求要经过强缓存和协商缓存的完整过程后才能决定。

13.http和https区别以及哪个更安全

http明文传输,数据没有加密,安全性较差。

https(http+ssl)数据传输过程是加密的,安全性更好一些。

使用https协议要经过ssl认证来申请ssl证书,认证拿到证书一般都是收费的,成本略高。

http的速度要比https要更快一些,就是因为http和服务器建立连接要通过TCP的三次握手,客户端和服务器只需要交换3个包,https在进行连接的时候除了要tcp的3个包,还要加上ssl握手的9个包,一共12个包。

14.工作中的跨域问题

在线上的各种环境中,一般是不会有跨域问题的,因为服务器和前端资源一般都是会部署在同一个域的服务器下,但是也有端口不同或不同域的情况,这些时候往往都是由后端去利用cors来处理跨域问题。

在本地开发的过程中,有些时候需要前端在脚手架对应的devServer中配置Proxy来进行开发时候的跨域处理。

15.事件循环

JavaScript是单线程的,这意味着它一次只能执行一个任务。为了处理异步操作,JavaScript引入了事件循环的概念。事件循环的工作机制可以分为以下几个部分:

  • 调用栈(Call Stack):用于存放执行中的函数。每当一个函数被调用时,它就被推入栈中,执行完成后就从栈中弹出。

  • 任务队列(Task Queue) :存放待执行的任务。包括宏任务(Macro Task)和微任务(Micro Task)。宏任务包含事件回调、setTimeoutsetInterval等;微任务则包括Promise.then()async/await等。

  • 事件循环(Event Loop):负责监控调用栈和任务队列。当调用栈为空时,事件循环会将任务队列中的第一个任务推入调用栈执行。

事件循环的工作流程如下:

  1. 执行主线程中的同步代码,放入调用栈中执行。
  2. 当遇到异步操作时,将其注册到相应的任务队列中。
  3. 执行完所有同步代码后,检查调用栈。
  4. 如果调用栈为空,事件循环会从微任务队列中取出并执行所有微任务(直到队列为空)。
  5. 微任务队列执行完后,事件循环会检查宏任务队列,取出第一个宏任务并执行。
  6. 重复以上步骤,直到所有任务完成。

16.宏任务和微任务

在 JavaScript 中,任务(Tasks)分为宏任务(Macrotasks)和微任务(Microtasks),它们在事件循环(Event Loop)中执行顺序不同。了解它们的区别有助于更好地理解 JavaScript 的异步编程模型。

1. 事件循环(Event Loop)

JavaScript 是单线程的,意味着它在任何时刻只能执行一个任务。为了处理异步操作,JavaScript 引入了事件循环。事件循环会不断检查执行栈(Call Stack)是否为空,如果为空,它会检查微任务队列和宏任务队列。

2. 宏任务(Macrotasks)

宏任务是相对较大的任务,通常会包含一段代码或一个事件的回调函数。它们主要来自以下几种操作:setTimeout,setInterval,I/O 操作,UI 渲染

执行顺序:宏任务的执行顺序是先执行一个宏任务,然后再处理所有的微任务,接着再执行下一个宏任务。

3. 微任务(Microtasks)

微任务是更小的任务,通常是一些需要在当前宏任务执行完成后立即执行的任务。它们主要来自以下几种操作:Promise.then.catch,MutationObserver,queueMicrotask 函数

执行顺序:微任务会在每个宏任务完成后立即执行。即在执行栈为空的情况下,事件循环会优先执行所有微任务队列中的任务,直到微任务队列清空后,才会继续执行下一个宏任务。

17.http状态码

1xx(信息性状态码)
  • 100 Continue:表示初始部分的请求已经接受,客户端可以继续发送请求的剩余部分。
  • 101 Switching Protocols:表示服务器正在根据客户端的请求更改协议。
2xx(成功状态码)
  • 200 OK:请求成功,服务器已返回所请求的数据。
  • 201 Created:请求成功并创建了新的资源,通常用于POST请求。
  • 202 Accepted:请求已接受,但尚未处理完成,通常用于异步处理。
  • 204 No Content:请求成功,但没有返回任何内容,通常用于DELETE请求。
3xx(重定向状态码)
  • 300 Multiple Choices:请求的资源有多种选择,客户端需要进一步选择。
  • 301 Moved Permanently:请求的资源已被永久移动到新位置,返回的新URI在响应中提供。
  • 302 Found:请求的资源临时移动到另一个URI,客户端应继续使用原URI进行以后的请求。
  • 304 Not Modified:请求的资源未被修改,客户端可使用缓存的版本。
4xx(客户端错误状态码)
  • 400 Bad Request:请求格式无效,服务器无法理解请求。
  • 401 Unauthorized:请求需要用户身份验证,客户端必须提供认证信息。
  • 403 Forbidden:服务器理解请求,但拒绝执行,通常由于权限问题。
  • 404 Not Found:请求的资源不存在,服务器无法找到所请求的URI。
  • 408 Request Timeout:客户端没有在服务器预期的时间内发送请求。
5xx(服务器错误状态码)
  • 500 Internal Server Error:服务器遇到意外情况,无法完成请求。
  • 501 Not Implemented:服务器不支持请求的功能,无法处理请求。
  • 502 Bad Gateway:作为网关或代理的服务器接收到无效响应。
  • 503 Service Unavailable:服务器当前无法处理请求,通常是由于过载或维护。
  • 504 Gateway Timeout:作为网关或代理的服务器未能及时从上游服务器获取响应。

18一个页面从输入url到页面加载显示完成,这个过程中都发生了什么?

1. 输入 URL
  • 用户输入:用户在浏览器地址栏中输入 URL(统一资源定位符),并按下回车键。
2. 解析 DNS
  • DNS 查询:浏览器会检查缓存中是否有该 URL 对应的 IP 地址。如果没有,浏览器会向 DNS 服务器发送请求,将域名解析为 IP 地址。
  • 响应返回:DNS 服务器返回对应的 IP 地址。
3. 建立 TCP 连接
  • TCP 握手:浏览器使用 TCP(传输控制协议)与服务器建立连接。这个过程通常包括三次握手(SYN, SYN-ACK, ACK)。
  • 加密连接(可选):如果 URL 使用 HTTPS,浏览器会与服务器进行 SSL/TLS 握手,建立加密连接。
4. 发送 HTTP 请求
  • 构建请求:浏览器生成 HTTP 请求报文,包括请求方法(如 GET 或 POST)、请求头、请求参数等。
  • 发送请求:浏览器通过已建立的 TCP 连接将 HTTP 请求发送到服务器。
5. 服务器处理请求
  • 接收请求:服务器接收到 HTTP 请求并开始处理。
  • 业务逻辑处理:服务器根据请求的 URL 和参数,执行相应的业务逻辑(如查询数据库、调用其他服务等)。
  • 生成响应:服务器生成 HTTP 响应报文,包括状态码、响应头和响应体(如 HTML、CSS、JavaScript、图片等)。
6. 接收 HTTP 响应
  • 返回响应:服务器将 HTTP 响应发送回浏览器。
  • 关闭连接:如果使用 HTTP/1.1,连接可能会保持开放以便后续请求;如果使用 HTTP/1.0,连接将会关闭。
7. 渲染页面
  • 解析 HTML:浏览器接收到 HTML 响应后,开始解析和构建 DOM(文档对象模型)。
  • 加载外部资源 :在解析 HTML 时,浏览器发现外部资源(如 CSS、JavaScript、图片等),会并行发送请求加载这些资源。
    • CSS:加载 CSS 资源,构建 CSSOM(CSS 对象模型)。
    • JavaScript:加载 JavaScript 文件,并执行代码(会影响 DOM 和 CSSOM)。
  • 构建 Render Tree:浏览器将 DOM 和 CSSOM 合并,生成 Render Tree(渲染树)。
8. 页面绘制
  • 布局(Reflow):浏览器计算每个元素在页面上的位置和大小。
  • 绘制(Paint):将页面内容绘制到屏幕上。
9. 交互和动态更新
  • 事件监听:浏览器开始监听用户的交互(如点击、输入等)。
  • 动态更新:如果有 JavaScript 代码在运行,可能会对 DOM 和 CSSOM 进行修改,从而触发重新布局和绘制。
10. 完成加载
  • 加载事件 :当所有资源加载完成后,浏览器会触发 load 事件,表示页面加载完成,用户可以进行交互。
相关推荐
理想不理想v10 分钟前
【经典】webpack和vite的区别?
java·前端·javascript·vue.js·面试
聊无生36 分钟前
JavaSrcipt 函数高级
开发语言·前端·javascript
好开心331 小时前
javaScript交互案例2
开发语言·前端·javascript·html·ecmascript·交互
duansamve2 小时前
WebGIS地图框架有哪些?
javascript·gis·openlayers·cesium·mapbox·leaflet·webgis
_jacobfu2 小时前
mac2024 安装node和vue
前端·javascript·vue.js
羽羽Ci Ci2 小时前
axios vue.js
前端·javascript·vue.js
halo14162 小时前
uni-app 界面TabBar中间大图标设置的两种方法
开发语言·javascript·uni-app
货拉拉技术2 小时前
多元消息融合分发平台
javascript·后端·架构
前端青山3 小时前
webpack进阶(一)
前端·javascript·webpack·前端框架·node.js
不熬夜的臭宝4 小时前
每天10个vue面试题(九)
javascript·vue.js·ecmascript