| |
|
开发:
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知识库]前端面试题(一) |
1.介绍一下box-sizing的属性? 1.box-sizing 规定两个并排的带边框的框, 2.box-sizing的属性值:content-box/border-box/inherit content-box:(默认的盒子,设置padding和border会撑开盒子,使盒子比原本的宽高更大,padding=>内边距,margin=>外边距)宽度和高度分别应用到元素的内容框,在宽度和高度之外绘制元素的内边距和边框 . border-box:(包含了padding和border,设置两者不会撑开盒子,盒子大小不会改变)为元素设定的宽度和高度决定了元素的边框盒.就是说,为元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制。通过从已设定的宽度和高度分别减去边框和内边距才能得到内容的宽度和高度。 inherit:继承父元素的 box-sizing. 2.浮动元素引起的问题和解决方法? (1)浮动元素引起的问题? 1.由于浮动元素已脱离文档流,所以父元素无法被撑开,影响与父级元素同级的元素。 (2)清除浮动的方式: 1.使用带 clear 属性的空元素 在浮动元素后使用一个空元素如<div class="clear"></div>,并在 CSS 中赋 予.clear{clear:both;}属性即可清理浮动。亦可使用<br class="clear" />或<hr class="clear" />来进行清理。 2.使用 CSS 的 overflow 属性 给浮动元素的容器(父元素)添加?overflow:hidden;或 overflow:auto;可以清除浮动,另外在 IE6 中还 需要触发 hasLayout ,例如为父元素设置容器宽高或设置 zoom:1。在添加 overflow 属性后,浮动元素又回到了容器层,把容器高度撑起,达到了清理浮动的效果。 3.给浮动的元素的容器添加浮动? 给浮动元素的容器也添加上浮动属性即可清除内部浮动,但是这样会使其整体浮动,影响布局,不推荐使用。 4.使用邻接元素处理 什么都不做,给浮动元素后面的元素添加 clear 属性。 5.使用 CSS 的:after 伪元素 结合:after 伪元素(注意这不是伪类,而是伪元素,代表一个元素之后最近的元素)和 IEhack ,可以完美兼容当前主流的各大浏览器,这里的 IEhack 指的是触发 hasLayout。给浮动元素的容器添加一个?clearfix 的 class,然后给这个 class 添加一个:after 伪元素实现元素末尾添加一个看不见的块元素(Block element)清理浮动。 即:给父元素添加clearfix样式:
3.什么是BFC? ????????BFC 也就是常说的块格式化上下文,这是一个独立的渲染区域,规定了内部如何布局, 并且这个区域的子元素不会影响到外面的元素,其中比较重要的布局规则有内部 box 垂 直放置,计算 BFC的高度的时候,浮动元素也参与计算,触发 BFC 的规则有根元素, 浮动元素,position 为absolute 或 fixed 的元素,display 为 inline-block,table-cell,table-caption,flex,inline-flex,overflow 不为 visible 的元素. 4.哪些操作会造成内存泄漏,怎么解决? 内存泄漏:指一块被分配的内存既不能使用,又不能回收,无法被释放.,直到浏览器进程结束。 1.意外的全局变量引起的内存泄露
2.闭包引起的内存泄露
闭包可以维持函数内局部变量,使其得不到释放。 上例定义事件回调时,由于是函数内定义函数,并且内部函数--事件回调的引用外暴了,形成了闭包。 解决之道,将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。
3.没有清理的DOM元素引用 DOM引用造成内存泄漏:Dom 的操作,会把Dom 的引用保存在一个数组或者 Map 中,标记已经移除,DOM对象还在内存中
4.被遗忘的定时器或者回调
这样的代码很常见, 如果 id 为 Node 的元素从 DOM 中移除, 该定时器仍会存在, 同时, 因为回调函数中包含对 someResource 的引用, 定时器外面的 someResource 也不会被释放。 5.子元素存在引起的内存泄露 ?黄色是指直接被 js变量所引用,在内存里,红色是指间接被 js变量所引用,如上图,refB 被 refA 间接引用,导致即使 refB 变量被清空,也是不会被回收的子元素 refB 由于 parentNode 的间接引用,只要它不被删除,它所有的父元素(图中红色部分)都不会被删除。 6.IE7/8引用计数使用循环引用产生的问题
fn()执行完毕后,两个对象都已经离开环境,在标记清除方式下是没有问题的,但是在引用计数策略下,因为a和b的引用次数不为0,所以不会被垃圾回收器回收内存,如果fn函数被大量调用,就会造成内存泄漏。在IE7与IE8上,内存直线上升。 7.怎样避免内存泄露? 1)减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收; 2)注意程序逻辑,避免“死循环”之类的 ; 3)避免创建过多的对象 ?原则:不用了的东西要及时归还。 5.浏览器的本地存储方案有哪些以及使用场景是什么? 1.sessionStorage存储 sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问,并且当会话结束后数据也随之销毁。sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。 2.localStorage存储 localStorage:主要是用来作为本地存储使用的,解决了cookie存储空间不足的问题(cookie的每条cookie存储不超过4k),localStorage中一般浏览器支持的是5M大小,这个在不同浏览器会有所不同。localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。 3.globalStorage Firefox支持globalStorage,能读写所有域的存储数据的localStorage。但是Firefox 13.0后被废弃了。 例子: globalStorage[‘developer.mozilla.org’] 解析: 在developer.mozilla.org下面所有的子域都可以通过这个存储对象来进行读和写。 4.Cookie 1.创建cookie ????????document.cookie="name=小明" 2.添加cookie有效期,时间是UTC格式 ????????document.cookie = "name=小明; expires=Sun, 31 Dec 2017 12:00:00 UTC"; 3.设置path 参数告诉浏览器 cookie 属于什么路径。默认情况下,cookie 属于当前页。 ????????document.cookie = "name=小明; expires=Sun, 31 Dec 2017 12:00:00 UTC; path=/"; 4.读取cookie ????????var cookie=doucument.cookie ????????console.log("cookie:"+cookie) 打印出来的结果: 会在一条字符串中返回所有 cookie,比如:cookie1=value; cookie2=value; cookie3=value; 5.删除cookie:利用expires参数,将cookie的有效期设置为过去的时间 ????document.cookie="name=小明;expires=Sun,29 Dec 2017 12:00:00 UTC ;path/" 注意:定义 cookie 路径以确保删除正确的 cookie。 6.创建cookie函数 ????function setCookie(cname, cvalue, exdays) { ????????????var d = new Date(); ????????????d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));//设置cookie的有效期 ????????????var expires = "expires="+d.toUTCString(); ????????????document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; ????????????} 7.获取cookie函数 ???function getCookie(cname) { ??????????????var name = cname + "="; ??????????????var ca = document.cookie.split(';'); ??????????????for(var i = 0; i < ca.length; i++) { ??????????????var c = ca[i]; ??????????????while (c.charAt(0) == ' ') { ?????????????????c = c.substring(1); ??????????????} ??????????????if (c.indexOf(name) ?== 0) { ?????????????????return c.substring(name.length, c.length); ??????????????} ????????????} ????????????return ""; ????} 8.检查cookie函数 ???function checkCookie() { ????var user = getCookie("username"); ????if (user != "") { ????????alert("Welcome again " + user); ????} else { ????????user = prompt("Please enter your name:", ""); ????????if (user != "" && user != null) { ????????????setCookie("username", user, 365); ????????} ????} console.log("时间:"+new Date().getTime()) } 6.Js去重的方法有哪些?
1.双重for循环
2.reduce()
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。 reduce() 可以作为一个高阶函数,用于函数的 compose。 注意:?reduce() 对于空数组是不会执行回调函数的。 3.Map() has方法可以判断Map对象中是否存在指定元素,有则返回true,否则返回false
4.for 循环:
5.every() every() 方法用于检测数组所有元素是否都符合指定条件,所有元素都满足条件,则返回 true,有一个元素不满足,则返回 false ,且剩余的元素不会再进行检测.
这几种方法都是用 对象的某个key做为唯一标识,相同则删除! 7.Js对象的浅克隆和深克隆的区别是什么以及实现方式是什么? 浅克隆:浅复制只复制一层对象的属性. 深克隆本质上是创造一个完全一样的对象,但是两个对象的引用地址完全不同,也就是不同与浅克隆,一个对象的改变,另外一个对象并不会发生改变。 浅克隆是指:只克隆数组/对象的第一层级内容(开辟新的堆内存),而第二层级及以上层级的内容则直接引用(使用原来第二层级及以上层级的堆内存)。如果对克隆后对象的二级或以上层级进行修改,那么克隆前对象的二级或以上层级也会跟着被修改。 1.对象的浅克隆方案一:基于循环实现
2.对象的浅克隆方案二: 展开运算符
3.对象的浅克隆方案三:基于Object.assign()函数 Object.assign([obj1], …[obj2]):该方法接收多个参数,执行后会将obj2中的键值对合并到obj1中,并将obj1的堆内存地址返回。注意:这里返回的不是新的对象,而是把第一个参数作为返回值返回。所以我们可以利用这个特点进行对象的浅克隆
4.数组浅克隆方案一:基于forEach或map
5.数组浅克隆方案二:基于展开运算符或Object.asing(),与对象相同
6.数据浅克隆方案三:基于数组的slice方法,不传参数默认从数组第一项开始截取到数组的最后一项
7.数组和对象的浅克隆 - 通用方案
深克隆:用递归复制了对象的所有层级. 浅克隆是指在克隆对象时,对于基本数据类型的变量会重新复制一份,而对于引用类型的变量只是对引用进行克隆。就是将栈中的值复制一份给新的变量,因为浅复制只会将对象的各个属性进行依次复制,并不会进行递归复制,而 JavaScript 存储对象都是存地址的,所以浅复制会导致两个对象指向都是同一个地址,一个发生改变另外一个也发生改变。 前面说浅克隆是只克隆数组或对象的第一层级,二级及以上层级是直接引用;那么深克隆则是克隆数组或对象的每个层级,不管一个对象或数组有多少层级,那么当我们进行深克隆时每一个层级都会开辟一块新的堆内存地址。对于克隆后对象/数组的任何层级做任何修改都不会影响到克隆前的对象/数组,因为它们都是独立的不同的堆内存。 1.数组和对象的深克隆:基于JSON.stringfiy、JSON.parse实现深克隆 原理:先将数组或对象基于JSON.stringify转换为字符串,然后再基于JSON.parse把字符串转换为对象,此时对象中对应每个层级都会开辟一块全新的堆内存来存储 ????????正则/Math数学函数会被处理为空对象
2. 数组/对象深克隆:
3.深克隆(函数、日期格式、正则有点问题)
项目中很多时候我们用这种方式就够了,因为很少会遇到对象里有函数、正则、日期格式这样的。 4.深克隆(层级递归) 由浅克隆的问题,可以知道,我们只要把每一层都遍历到,并赋值给新的对象的每一项的每一层级即可。那么就会想到——递归
8.谈谈你对闭包的理解。你有哪些性能优化的方法? 简单来说,闭包就是在函数里面声明函数,实际开发中主要应用于封装变量,保护变量不受外界污染,也相当于是在函数作用域里面再声明一个内部作用域,这样执行结果拿到的变量都是不同的,拿的就不是全局变量。 特性:函数内部嵌套函数 缺点:闭包容易消耗内存 注意:子函数可以访问父函数中所有的局部变量,,但是父函数不能访问子函数的变量 创建:创建闭包最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用域链,将函数内部的变量和方法传递到外部。 闭包解决方法:在函数结束之前,把局部变量删除。 9.为什么vue组件中的data必须是一个函数?? ????????类比引用数据类型。Object是引用数据类型,如果不用function 返回,每个组件的data 都是内存的同一个地址,一个数据改变了其他也改变了; ????????javascipt只有函数构成作用域(注意理解作用域,只有函数的{}构成作用域,对象的{}以及 if(){}都不构成作用域),data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响。 例:
如果两个实例同时引用一个对象,那么当你修改其中一个属性的时候,另外一个实例也会跟着改; 两个实例应该有自己各自的域才对,需要通过下面的方法来进行处理。
????????这样的话一个实例的data属性都是独立的,不会相互影响了. 10.什么是virtual DOM ? ????????所谓的 virtual dom,也就是虚拟节点。它通过 JS 的 Object 对象模拟 DOM 中的节点,然后再通过特定的 render 方法将其渲染成真实的 DOM 节点。 ????????其次我们还得知道一点,那就是 virtual dom 做的一件事情到底是啥。我们知道的对于页面的重新渲染一般的做法是通过操作 dom,重置 innerHTML 去完成这样一件事情。而 virtual dom 则是通过 JS 层面的计算,返回一个 patch 对象,即补丁对象,在通过特定的操作解析 patch 对象,完成页面的重新渲染。(改变需要改变的部分,其他地方不动!) 11.key属性的作用什么? ????????当 Vue.js 用v-for正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。(*如果不用key,则会都改变许多顺序,用key则会改变需要改变的地方!) ????????总体来说,当使用列表渲染时,永远添加key属性,这样可以提高列表渲染的效率,提高了页面的性能。 使用key属性强制替换元素: ????????key属性还有另外一种使用方法,即强制替换元素,从而可以触发组件的生命周期钩子或者触发过渡。因为当key改变时,Vue认为一个新的元素产生了,从而会新插入一个元素来替换掉原有的元素。key属性被用在组件上时,当key改变时会引起新组件的创建和原有组件的删除,此时组件的生命周期钩子就会被触发。 12.vue2和vue3的区别是什么? 1. vue2和vue3双向数据绑定原理发生了改变。 vue2 的双向数据绑定是利用ES5 的一个 API Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。vue3 中使用了 es6 的 ProxyAPI 对数据代理。 相比于vue2.x,使用proxy的优势如下: ????????defineProperty只能监听某个属性,不能对全对象监听。 ????????可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)。 ????????可以监听数组,不用再去单独的对数组做特异性操作 vue3.x可以检测到数组内部数据的变化? 2. 默认进行懒观察(lazy observation)。 ????????在 2.x 版本里,不管数据多大,都会在一开始就为其创建观察者。当数据很大时,这可能会在页面载入时造成明显的性能压力。3.x 版本,只会对「被用于渲染初始可见部分的数据」创建观察者,而且 3.x 的观察者更高效。 3. 更精准的变更通知。 ????????比例来说:2.x 版本中,使用 Vue.set 来给对象新增一个属性时,这个对象的所有 watcher 都会重新运行;3.x 版本中,只有依赖那个属性的 watcher 才会重新运行。 4. 3.0 新加入了 TypeScript 以及 PWA 的支持 5.vue2和vue3组件发送改变 6.vue3.0的设计目标
13.封装后的高阶组件?
14.react优化? 15.前端性能优化? (3)通过设置缓存策略,对常用不变的资源进行缓存。 第二个方面是服务器方面 (2)避免使用@import标签。 16.组件优化? 17.proxy 代理(拦截器)? 2.当我的变量显示或改变的时候,会调用proxy的两个方法,get和set。 3.get 方法默认就会调用,set方法当变量改变的时候去调用。 18.webpack常用loader? 3. style-loader:将样式通过<style></style>标签插入<head></head>之间 ? ? ? ? (2)file-loader将文件或图片改名并复制到打包目录. 7. thread-loader多进程打包 js和css 10.raw-loader来实现静态资源内联. 19.扁平化? 1.es5扁平化:
2.es6扁平化:
3.迭代删除数组里某几项内容:
4.先排序后去重
5.sum函数:
20.mock的作用,平时怎么搭建? mock模拟的是后端调来的数据(假数据),在开发中如果后端进度跟不上,可以使用mock代替后端数据,当后端数据写完后,再改地址调接口取数据,用法?export?js文件,import接收,如果webpack没有支持json文件需要设置json文件,再进行接收. 21.什么是hoc,举例说明? 高阶组件就是hoc,高阶组件就是一个获取一个组件并返回一个组件的函数,react-redux?的conect就是一个高阶组件。 22.写出redux里dispatch和action的具体作用? ????????dispatch:用于action分发,可以用中间件对dispatch进行改造,比如当action传入dispatch会立即触发reducer有时候我们不希望它立即触发,而是等待异步操作完成后再触发,这时候用redux-thunk对dispatch进行改造,以前只能传入一个对象,改造完成后可以传入一个函数,在这个函数里我们手动dispatch一个action对象这个过程是可控的,就实现了异步; ????????action(处理类型不一样处理方法不同)根据action的type类型不同会返回不同的reducer。 23.写出mwm模式和mvc模式区别? mvvm是双向数据流,mvc是单数据。两者都由m(模型)、v(视图) 不同的是:mvvm内由vm(模型视图)负责业务逻辑,mvc由c(控制器)负责业务逻辑 24.react的生命周期?(实际项目组用到的react生命周期钩子有哪些?都是在什么时候触发的?)? 实际项目中用的react生命周期方法,在初始化阶段,es5中用到getDefaultProps和getInitialState,es6中通过类的继承从component中继承,挂载阶段实际项目中用到的是render和componentDidMount,render在state和props更新时被调用,子组件的render会在父组件的render执行时被执行,更新阶段一般不覆盖更新阶段的钩子函数,所以在开发时不会用到,卸载阶段一般不用,所以卸载阶段的钩子函数也不用,修改后的生命周期方法: componentWillMount()=>组件挂载前? 和componentWillUpdate()=>组件更新后 ?1.React16新的生命周期弃用了componentWillMount、componentWillReceivePorps, componentWillUpdate 25.为什么虚拟dom会提高性能? 虚拟DOM相当于在js和真实DOM之间加了一个缓存,利用dom,diff算法避免了没有必要的dom操作从而提高性能。 26.React组件间通信? 1.父组件通过props/this.props给子组件传值 ??????子组件通过父组件传递过来的回调函数的参数给父组件传值 ????????App--todo->Item ?Item--changHasCompleted(todo)->App ?????????说明:适合于不超过三层 2.redux 集中式数据管理--通用的数据流解决方案 3.context 4.事件订阅 27.react传值的方法? 1.通过props属性实现组件间传值。 2.通过prop-types的context实现跨级组件传值。 3.使用事件订阅实现组件间跨级传值。 4.使用redux实现组件跨级通信. 28.生命周期方法? 从组件创建,到组件的更新,直到组件销毁过程中,按照固定的顺序自动调用的方法。 ??1.getDefaultProps ?es6改为 类名.state ?初始化属性 ??2.getInitialState ?es6改为 this.state ?初始化状态 ??3.componentWillMount ?渲染组件前调用,在客户端也在服务端 ??4.render ?渲染组件 ??5.componentDidMount ?在第一次渲染组件后调用,只在客户端 ??6.componentWillReceiveProps ?准备接收属性(在组件接收到一个新的prop时被调用) ??7.shouldComponentUpdate ?是否更新组建,返回一个布尔值,在组件接收到新的props或state时被调用 ??8.componentWillUpdate ?准备更新组件(在组件收到新的props或者state但还没有render时被调用) ??9.componentDidUpdate ?更新组建后(在初始化时不会被调用) ??10.componentWillUnmount ?准备卸载组件(在组件从dom中移除的时候立刻被调用) React15版本的生命周期: React 16版本的生命周期: ? 废弃了: componentWillMount、componentWillReceiveProps、componentWillUpdate。 新增了: 1.static getDerivedStateFromProps(props, state) 组件每次被rerender的时候,包括在组件构建之后(虚拟dom之后,实际dom挂载之前),每次获取新的props或state之后;每次接收新的props之后都会返回一个对象作为新的state,返回null则说明不需要更新state;配合componentDidUpdate,可以覆盖componentWillReceiveProps的所有用法。 2.getSnapshotBeforeUpdate(prevProps, prevState) 触发时间:?update发生的时候,在render之后,在组件dom渲染之前;返回一个值,作为componentDidUpdate的第三个参数;配合componentDidUpdate, 可以覆盖componentWillUpdate的所有用法。 ??3. Error Handling(错误处理) componentDidCatch(error,info)? 任何一处的javascript报错会触发。 ?29.React特点? ? 1.较高的性能:虚拟DOM、diff算法 ??2.虚拟DOM--js对象 ??3.组件化--实现代码高度复用 ??4.JSX语法:用xhtml写DOM对象 ??5.单向数据流 父--->props->子 30.react脚手架? 1.从webpack开始,纯手工独立搭建的webpack脚手架 2.facebook官方提供create-react-app ?0配置脚手架 3.roadhog 0配置脚手架 31.react组件传值? 1.父组件向子组件传值 (通过props来传值) 2.子组件给父组件传值 (回调函数) 3.兄弟组件传值(子组件传给父组件,由父组件再传给另外一个子组件) 32.react组件分类? 1.静态组件--函数 2.类组件 --class ??????--ES5 React.createClass({}); ??? ??????--ES6 extends React.Component。 33.redux?redux的原理了不了解?(redux的实现过程--分几块?)? ????????edux主要是数据中心化和跨级通信。 ????????数据中心化实现是通过创建全局store,在store中创建state树,存储数据。 ????????跨级通信是通过provider组件包裹入口组件,然后在入口组件及入口组件的后代组件中通过高阶组件connect连接store,获取数据。 34.redux的原理及缺点? ????创建一个全局store,store中存放着多条state状态,哪里需要用state哪个组件就connect链接到全局store中,更改store需要发送dispatch(action)到reducer中,reducer更改state后,页面重新渲染 (忘了就去看一下举火库那张图) ????缺点: 需要维护大量constant,action,reducer 35.redux-saga 中间件和工作流程? 中间件: 中间件 ?或 中间件函数 ?redux middleware 中间:因为middleware位于 action 和reducer之间 Redux第三方中间件:redux-thunk 中间件执行原理:拦截action,然后转发action 工作流程: redux-saga:用于异步处理ajax的中间件 ?????--解决回调地狱的问题 ?????--实现异步操作 优势:可读性强 可维护强。 36.redux ?redux-saga开发中存在的问题? 1.文件非常多-难以维护 ???constants ???actions ???reducers ???sagas 2.代码冗余 ??综上所述,开发和维护困难 |
|
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年11日历 | -2024/11/23 9:27:37- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |