| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> JavaScript知识库 -> 前端面试题详解 -> 正文阅读 |
|
[JavaScript知识库]前端面试题详解 |
浏览器前言? 最近正好在找工作,整理一下可能问到的和遇到过的面试题。 HTMLHTML语义化标签HTML5新增的语义化标签有:header、nav、main、article、aside、footer等等。 HTML语义化就是让页面内容结构化,他有以下优点:
HTML5新标签HTML5新增的标签有:header、nav、video、audio、canvas、aside等等。 HTML5新增了哪些内容广义上的HTML5指的是最新一代前端开发技术的总称,包括:HTML5、CSS3、新增的webStorage等webAPI。 HTML中新增了header、footer、nav等语义化标签,还新增了video、audio媒体标签,新增了canvas画布,还有一些标签的新属性,比如:input标签的placeholder属性。 CSS中新增了圆角、阴影、滤镜、vw和vh长度单位,flex布局,媒体查询,过度和动画,伪类等。 js中新增了webStorage浏览器缓存策略、querySelector、webSocket、requestAnimationFrame、Worker线程、地理位置等。 HTML5中的form的自动完成功能是什么
自动完成允许浏览器预测对字段的输入。在用户在字段开始键入时,浏览器基于之前键入的值,应该显示出在字段中的选项。 多个浏览器标签页之间的通信浏览器标签页之间是没办法直接通信的,一般都是通过找一个中介者来实现通信。
H5中cookie的原理cookie就是HTML5提供的一种缓存方式,一个cookie就是存储在用户主机浏览器中的一小段文本文件。Cookies是纯文本形式,他们不包含任何可执行代码。每个cookie相当于一个用户标识,在该页面发送请求时,会携带对应页面存储的cookie值发送给后端用来判断登录状态是否失效。 cookie还可以用来存储数据,但是浏览器供cookie存放数据的空间较少,如果需要存放大容量数据,推荐使用webStorage。 CSSCSS盒模型盒模型分为标准盒模型和ie盒模型。标准盒模型为content(内容)+padding(内边距)+border(边框)+margin(外边距),而ie盒模型则为content(内容)+padding(内边距)+margin(外边距)。 标准盒模型和ie盒模型最根本的区别在于标准盒模型将边框的单位长度单独算了进去,而ie盒模型没有算进去,ie盒模型将边框的单位长度算进内边距中。 可以通过box-sizing进行标准盒模型和ie盒模型之间的转换。 标准盒模型:box-sizing: content-box; ie盒模型:box-sizing: border-box; rem和em的区别rem和em都是css的长度单位,rem是相对于根元素html的font-size进行变化,em是根据父元素的fong-size进行变化的。 CSS选择器常用的选择器 通配符选择器:* ID选择器:#ID 类选择器:.class 元素选择器:p、a、span等 后代选择器:p span、div a等 伪类选择器:a:hover、a:active等 属性选择器:input[type="text"]等 CSS选择器权重 !import > 行内样式 > #id > .class > 元素和伪元素 > * > 继承 > 默认 CSS精灵图在CSS中,多个图标集成到一张图上使用background-position属性设置的图片,称为精灵图(又称图片精灵)。 CSS新特性transition: 过渡 transform: 旋转、缩放、移动或者倾斜 animation: 动画 gradient: 渐变 shadow: 阴影 border-radius: 圆角 元素性质:行内元素和块级元素行内元素(display: inline) 宽度和高度是由内容决定的,与其他元素共占一行不能设置宽高,例如:span标签、a标签、i标签等等 块级元素(display: block) 默认宽度由父容器决定,默认高度由内容决定,并且独占一行可以设置宽高,例如:p标签、div标签、ul标签等。 行内块元素(display: inline-block) 宽度和高度由内容决定,与其他元素共占一行但是可以设置宽高等,例如:img标签等。 绝对定位和相对定位position:absolute; 绝对定位,是相对于元素最近的已定位的父元素,如果没有已定位的父元素,就相对于body元素进行定位。 position:relative; 相对定位,是相对于元素在文档中的初始位置进行定位。 flex布局通过display:flex使该元素的子元素脱离文档流,进行一些其他的操作。 align-item: 定义元素横向排列规则 flex-direction: 定义元素纵向排列规则 justify-content: 定义在主轴上的对齐方式 BFCBFC格式化上下文,就是创作一个独立的渲染区域,让处于BFC内部的元素和外部相互隔离,使内外元素不受影响。 如何产生BFC 最有效的一种方式就是将元素的性质改变为行内块元素(display:inline-block),还可以通过position:absolute/relative进行产生bfc。 最不推荐的一种方式就是给元素添加边框,但是这种方式相比而言最简单。 BFC的作用
水平垂直居中通过flex布局或者line-height属性和text-align属性进行布置 less、sass和stylus的区别
link和@import的区别
多行元素的文本省略号overflow : hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; // 控制行数 -webkit-box-orient: vertical 重绘和回流(Repaint & Reflow)根据浏览器渲染机制(下方浏览器部分中有解释)可以得知HTML被解析解析成了DOM,CSS被解析成了CSSOM,它俩合并产生了渲染树Render Tree。 重绘 由于节点的集合属性发生改变或者由于样式改变而不会影响布局的,称为重绘。例如 回流 回流是布局或几何属性发生改变就称为回流。回流是影响浏览器性能的关键因素,因为其变涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致其素有子元素以及DOM中紧随其后的节点、祖先节点元素随后的回流。大部分的回流将导致页面的重新渲染。 回流必定会发生重绘,重绘不一定会引发回流。 JavaScriptJS的几条基本规范
JS引入方法行内引入 直接在标签的方法中执行js语句。 内部引入 在script标签中编写js代码,并执行 外部引入 通过script的src属性指向一个js文件的路径进行引入使用 JS的基本数据类型string、number、boolean、undefined、null、symbol六种基本数据类型。 数组操作循环 map函数、forEach函数、for循环、forin循环、forof循环。 过滤 filter函数 查找 对于一些简单函数可以直接使用 let p = [1, 2, 3]; console.log(1 in p) // true includes函数:查找匹配项,如果有返回true,没有返回false。 indexOf函数:正序查找匹配数据,返回下标。 lastIndexOf函数:倒叙查找匹配数据,返回下标。 some函数:有匹配项返回true时,整体为true。 every函数:有匹配项返回false时,整体为false。 添加 push函数:在数组的末尾添加一条数据。 unshift函数:在数组的开头添加一条数据。 删除 pop函数:在数组的末尾删除一条数据。 shift函数:在数组的开头删除一条数据。 slice(start, end)函数:根据参数截取数组,并返回一个新数组,不会影响原来的数组。 splice(start, end, value....)函数:根据参数删除数据并替换数据,返回当前操作后的数组,会影响原来的数组。 排序 sort函数:根据回调函数的具体逻辑将数组进行排列顺序。 reverse函数:将数组按照现在的数据顺序进行反转。 其他 concat函数:合并两个数组。 reduce函数:在回调函数中对数组的每一条数据进行操作。 JS内置对象Object是JavaScript中所有对象的父对象。 数据封装对象:Object、Array、Boolean、Number和String。 其他对象:Function、Arguments、Math、Date、Error、RegExp等。 闭包一个函数中包含了另一个函数,其中的函数使用到了第一个函数的变量,那么其中的函数就叫做闭包。 闭包就是能够读取其他函数内部变量的函数。 特征:
闭包的理解 使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点shi闭包会常驻内存,增大内存使用量,容易造成内存泄漏。在js中,函数即闭包,只有函数才会产生作用域的概念。 闭包最大的好处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中。 js中的同步和异步因为JavaScript是单线程编程语言,所以同步和异步并不是主线程执行同步代码,再开一个线程执行异步代码,而是通过消息队列和事件循环的方式来进行同步和异步的划分。 当js执行同步代码时,一个任务执行完才会去执行下一个任务,如果前一个任务耗时很长,那么后一个任务不得不一直等着,这样就会堵塞代码执行。 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行下一个任务。 异步任务指的是,不进入主线程、而进入消息队列的任务,只有等主线程任务执行完毕,任务队列开始通知主线程,请求执行任务,该任务才会进入主线程执行。 异步运行机制
JavaScript的运行机制简单来说就是同步任务和异步任务的组合。 主线程先执行同步任务,当执行完毕同步任务时,去读取"消息队列",并执行消息队列中的异步任务和其他事件,并且一直重复这个过程(只要主线程中的同步任务为空,就去读取"消息队列")。 注意: "消息队列"中除异步任务外,还有IO设备的事件以及一些用户产生的事件(比如鼠标点击、页面滚动等等),这些相对耗时的操作。只要指定过这些事件的回调函数,这些事件发生时就会进入"消息队列",等待主线程读取。 JS作用域和作用域链在js中作用域分为全局作用域和局部作用域。 全局作用域可以在程序的任何地方都能被访问,比如window对象的内置属性就具有全局作用域。 局部作用域只有在当前作用域内才能被访问,否则会报错"xxx is not defined"。 全局作用域可以通过var关键字来声明,也可以在程序的最外部通过let关键字声明。 局部作用域可以在程序的某个代码块中通过let关键字声明。 在使用变量的过程中,会先在当前作用域查找是否定义了这个变量,如果找不到,就会向上级作用域去查,直到查到全局作用域,这个查找的过程叫做作用域链。 原型和原型链在js中有一句话万物皆对象,每个对象都会在其内部初始化一个prototype属性,这个属性就是原型,当我们访问一个方法或者属性的时候,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又有自己的prototype,这个样一直找下去,直到找到Object内建对象,这个过程叫做原型链。 函数是一个另类,它具有两个原型,一个prototype,一个proto。 继承js中的继承分为两种,一种是es6的class类的继承,一种是构造函数的继承。 class类继承 es6中的类继承比较方便,可以直接通过 class f{ obj = { a: 1, b: 2 }, m: function(){ console.log(this.obj.a + this.obj.b); } } class n extends f{} es5构造函数继承 在js的es5版本中的继承是基于原型链的继承,并且必须是继承了原型属性、原型方法及原型才能算是真正的继承成功。 高阶函数在javascript中,函数的参数可以接收变量,所以一个函数作为另一个函数的参数的这种形式,称为高阶函数。 javascript中具有回调函数的操作数组的方法都是高阶函数。 ? ?? 函数柯里化js中的柯里化就是一个函数返回另一个函数,最后在调用的时候将函数的参数拆分调用。 简单的柯里化函数: // 简单函数 function sum(a, b){ return a + b; } // 柯里化后 function curry(a){ return function(b){ return a + b; } } // 调用 sum(1, 2); curry(1)(2); 组件和模块化当页面代码量过大,逻辑太多或者同一个功能组件在很多页面均有使用,维护起来相当麻烦,这个时候,就需要组件化开发来进行功能拆分、组件封装,达到组件通用性,增强代码得可读性,降低维护成本。 组件化开发的优点 很大程度上降低系统各个功能得耦合性,并且提高了内部功能得聚合性。这对前端工程化及降低代码得维护来说,是有很大的好处的,耦合性的降低,提高了系统的伸展性,降低了开发的复杂性,提升开发效率,降低开发成本。
模块化 出现模块化这个概念的原因是因为早期版本的js没有块级作用域、没有类、没有包、也没有模块,这样就带来了复用、依赖、冲突、代码组织混乱等一系列的问题,也就出现了模块化这一概念。 模块化的好处
模块化的几种方法
图片的预加载和懒加载
两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。预加载会增加服务器前端压力,懒加载对服务器有一定的缓解压力。 mouseover和mouseenter的区别mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡的过程。对应的移除事件为mouseout。 mouseenter:当鼠标移除元素本身(不包含子元素)会触发事件,也就是不会冒泡,对应的移除事件是mouseleave。 解决异步回调地狱通过promise、generator、async/await都可以解决。 对this对象的理解this总是指向函数的直接调用者(并非简介调用者)。 如果有new关键字,this指向new出来的那个对象。 在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window。 VUEVue生命周期Vue实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载DOM元素=>渲染、更新=>渲染、卸载等一系列过程,就是Vue的生命周期。 Vue的生命周期中有很多事件钩子,可以通过这些事件钩子更好控制整个Vue实例的渲染和其中的各种逻辑。 Vue生命周期总共有几个阶段 总共有8个阶段: 创建前(beforeCreate) => 创建后(created) => 载入前(beforeMount)=>载入后(mounted)=>更新前(beforeUpdate)=>更新后(updated)=>销毁前(beforeDestroy)=>销毁后(destroyed) DOM元素渲染在mounted中就已经完成了。 每个生命周期适合的场景 beforecreate : 可以在这加个loading事件,在加载实例时触发 created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用 mounted : 挂载元素,获取到DOM节点 updated : 如果对数据统一处理,在这里写上相应函数 beforeDestroy : 可以做一个确认停止事件的确认框 nextTick : 更新数据后立即操作dom v-show和v-if的区别v-show是通过切换元素的css属性,v-if是dom的销毁和重新创建。 使用频繁切换时应该用v-show,使用较少时用v-if。 开发中常用的指令v-html、v-model、v-bind、v-on、v-show、v-if、v-else-if、v-else等等。 动态化样式属性的方法对象方法:v-bind:class="{'origin': isRipe, 'green': isNotRipe}"。 数组方法:v-bind:class="[class1, class2]"。 行内绑定:v-bind:style="{color: color, fontSize: fontSize + 'px'}"。 组件通信父组件向子组件传值 在父组件中直接为子组件绑定自定义属性传递数据,子组件通过props接收。 父组件模板: <template> <Child :msg="message" /> </template> <script> export default{ template: { Child }, data(){ return { message: "向子组件传递的数据" } } } </script> 子组件模板: <template> {{ msg }} </template> <script> export default{ props: { // 也可通过数组写法,不进行类型检查和参数限定 msg: { type: String, required: true } } } </script> 子组件向父组件传递数据 因为vue遵循单向数据流,在子组件中无法直接向父组件传递数据,必须通过$emit()触发父组件中的方法并将数据通过参数的方式传递过去。 父组件模板: <template> <Child @msgFunc="func" /> </template> <script> export default{ template: { Child }, methods: { func(msg){ console.log(msg); // 打印子组件传递过来的数据 } } } </script> 子组件模板: <template> <button @click="handleClick()">触发父组件的方法,并传递过去数据</button> </template> <script> export default{ data(){ return { message: "子组件的数据" } }, methods: { handleClick(){ this.$emit("msgFunc", this.message); // 此处第二个参数有可能会不生效,推荐重定向下this指向。 } } } </script> 兄弟组件之间传值 兄弟组件之间传值可以通过Bus通信,或者vuex完成。 实例化一个vue实例作为Bus媒介,将该实例挂载到Vue原型链上方便调用,并通过$emit()和$on进行触发方法和传递数据。 main.js文件: import Vue from "vue"; let Bus = new Vue(); Vue.prototype.$Bus = Bus; new Vue({...}); 组件1: <template> {{ message }} </template> <script> export default{ data(){ return { message: "" } }, mounted(){ this.$Bus.$on("on", (msg) => { // 通过$on事件相应$emit事件 this.message = msg; }); } } </script> 组件2: <template> <button @lick="toBus()">触发on方法,并传递数据</button> </template> <script> export default{ data(){ return { msg: "兄弟组件中的数据" } }, methods: { toBus(){ this.$Bus.$emit("on", this.msg); } } } </script> Vue路由跳转的方式
MVVM什么意思MVVM,按从左到右的顺序,M代表Model数据模型,V代表View视图,VM代表ViewModel视图和数据的桥接器。 computed和watch有什么区别computed:
watch:
当我们需要进行数值计算,并且依赖于其他数据时,就使用computed。如果只是单纯的监听数据变化进行回调事件,那么就使用watch。 Vue中的key有什么作用key是Vue中节点的唯一标识符,可以使我们的diff操作更准确、快速。 如果不加key,vue会选择复用节点(Vue的就地更新策略),就会导致之前的节点的状态被保留下来,使节点更新不准确,并且不利于被Map数据结构充分利用。 组件中的data为什么是一个函数vue组件中data是一个函数并返回一个对象,而Vue实例中的data是一个对象。 这是因为在js中对象不具有作用域,而函数具有作用域。vue组件是用来复用的,必须是每个组件的作用域相互隔离的,不会相互影响,而new Vue()实例是不会被复用,因此不存在引用对象问题。 nextTick()在下一次DOM更新循环结束之后延迟执行回调。在修改数据之后,立即使用的这个回调函数,获取更新后的DOM。 vm.smg = "数据"; // DOM还未更新 Vue.nextTick(() => { // DOM更新 }); Vue插槽vue中拥有具名插槽、匿名插槽和作用域插槽三种,三种插槽都是通过<slot>标签进行分发内容,但作用域插槽是通过slot-scope属性进行分发内容。 具名插槽拥有name属性对父组件传过来的数据进行匹配并分发内容。 Vue的使用注意事项可以看下这篇博客,里面讲的优化非常好Vue项目性能优化 vue-router导航守卫在vue-router中可以通过添加meta属性对路由添加原信息进行路由权鉴,并且可以在vue-router的路由钩子中进行路由的重定向。 vue-router的路由钩子有三种: 第一种:全局导航钩子,router.beforeEach((to, from, next) = {}),在全局路由跳转之前进行拦截。 第二种:组件内的钩子。 第三种:单独路由独享钩子。 vuexvuex是vue的状态管理组件,其中的state就是数据源存放地,对应一般vue对象里面的data。 state中存放的数据是响应式的,vue组件从store读取数据,若是store中的数据发生改变,依赖该数据的组件也会发生更新。 可以通过mapState把全局的state和getters映射到当前组件的computed计算属性。 vuex有5中属性:分别是state、getter、mutation、action、module。 state Vuex使用单一状态树,即每个应用将仅仅包含一个store实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。 mutation 在其中定义用于动态修改Vuex的store中的数据状态的方法。 getter 相当于vue的计算属性,主要用来过滤一些数据。 action actions中定义的方法就是将mutation中的定义的处理数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。vue组件中通过store.dispatch()来分发action,也可以通过mapAction将action中的方法映射进methods中。 vuex一般用于中大型web单页应用中对应用的状态进行管理,对于一些组件间关系较为简单的小型应用,使用vuex的必要性不是很大,因为完全可以用组件props属性或者Bus事件来完成通信,vuex更多地用于解决跨组件通信以及作为数据中心集中式存储数据。 React虚拟DOM虚拟DOM相当于真实DOM的一个类对象,当应用的状态发生改变时,会记录新的虚拟DOM树并于原先旧的虚拟DOM树进行比较,再把其中发生的改变更新到真实DOM树上。 虚拟DOM的优点
虚拟DOM的缺点
React的生命周期React 16之后有三个生命周期被废弃,但没有移除,所以还是可以使用,不过官方并不推荐这样:
目前React16.8+的生命周期分为三个阶段,分别是挂载阶段、更新阶段、卸载阶段: 挂载阶段
更新阶段
卸载阶段
React应用中的请求应该放在哪个声明周期中如果将请求放在componentWillMount中可以提前进行异步请求,避免白屏,但是当React渲染一个组件时,他不会等待componentWillMount完成任何事情,React会继续执行render事件,没有办法暂停渲染以等待数据的到达。 而且在服务器渲染时,如果在componentWillMount中获取数据,fetch data会执行两次,一次在客户端一次在服务端,这造成了多余的请求,其次,在React 16进行React Fiber重写后,componentWillMount可能在一次渲染中多次调用。 官方推荐在componentDidMount中进行。如果有特殊需求需要提前请求,也可以在constructor中请求。 setState是同步还是异步的
React组件通信React中的组件通信和Vue中组件通信差不多,都分为父子组件通讯和其他组件通讯。 父子组件通讯
其他组件通讯
ES6var、let、const的区别var声明的变量不具有块级作用域,并且可以重复声明变量,声明后的变量会与window相映射,可以在window对象中查找到,并且var声明的变量具有变量提升,可以先使用后声明。 let声明的变量具有块级作用域,在同一个作用域内不可以重复声明名称相同的变量,并且let声明的变量不具有变量提升,必须先声明后使用。 const声明的是常量,一旦声明赋值过后就无法改变常量的值,并且支持块级作用域。 解构赋值可以通过数组或对象的形式将数组或对象中的单个数据获取出来。 // 对象解构 let {a, b} = {a: 1, b: 2}; // 数组解构 let [c, d, e] = [1, 2, 3]; 还可以将函数的参数通过对象解构的方式一一对应。 function personInfo({name, age, address, gender}){ console.log(arguments === {name, age, address, gender}); // true console.log(name, age, address, gender); } personInfo({gender: 'man', address: 'changsha', name: 'william', age: 18}); forEach、for in、for of的区别forEach更多的是用来遍历数组。 for in一般常用来遍历对象或json for of数组对象都可以遍历,遍历对象需要通过和Object.keys()配合 for in循环出来的是key,for of循环出的是value。 箭头函数箭头函数又称为lambda表达式,是一种简化函数定义的语法糖。 箭头函数可以省略参数那里括号和包裹执行语句的大括号,表示直接返回执行语句。 let example = value => console.log(value); 注意:
Set和MapSet用于数据重组,Map用于数据存储。 Set
Map
Promise对象Promise是一个构造函数,可以通过new关键字声明一个promise函数,它具有三种状态,并且调用它其中一个状态成功时就会凝固在这个状态上,不发生改变。 在Promise函数中可以通过then来调用它成功的状态,catch调用它失败的状态,finaly调用执行结束的状态。 let promise = new Promise((resolve, reject) => { if(true){ resolve(...); }else{ reject(...); } }); promise.then((...) => { ... }).catch((...) => { ... }); AJAX相关get请求传参HTTP协议并没有规定GET/POST的请求长度限制,对get请求参数的限制是来源与浏览器或者web服务器,浏览器或者web服务器限制了url的长度,并且,有以下几点:
get请求和post请求的区别
同步和异步的区别同步和异步最根本的区别在于,同步会阻塞代码执行,但是异步不会。 同步相当于只有一条车道,一条车走完过后下一辆车再走,如果中间出现了问题,久会发生阻塞现象。 异步可以理解为有很多条通道,好几辆车同时在不同的车道上行驶,并不会阻塞。 所有的ajax请求都是异步的。 ajax的优缺点优点
缺点
如何解决跨域问题跨域的概念:协议、域名、端口都相同才是同域,否则都是跨域。
TCP/IP协议族tcp协议是以太网协议和ip协议的上层协议,也是应用层协议的下层协议。 TCP协议的主要内容就是
上面的几个步骤可以用一张图来解释: 浏览器相关浏览器的渲染原理
渲染引擎并不会等到所有的HTML解析完成之后再去构建和布局Render Tree,而是解析一部分就构建一部分,相当于热更新一样。 从浏览器地址栏输入url到显示页面的步骤
|
|
JavaScript知识库 最新文章 |
ES6的相关知识点 |
react 函数式组件 & react其他一些总结 |
Vue基础超详细 |
前端JS也可以连点成线(Vue中运用 AntVG6) |
Vue事件处理的基本使用 |
Vue后台项目的记录 (一) |
前后端分离vue跨域,devServer配置proxy代理 |
TypeScript |
初识vuex |
vue项目安装包指令收集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/27 19:52:59- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |