2023年最新的前端面试收集(1)

一、你在项目中做的性能优化的事情有哪些

网络优化

  • DNS预解析

    • link标签的rel属性设置dns-prefetch,提前获取域名对应的IP地址
  • 使用缓存

    • 减轻服务端压力,快速得到数据(强缓存和协商缓存)
      1. 强缓存
      • 浏览器在访问某个资源时会判断是否使用本地缓存里已经存在的资源文件,使用本地缓存的话则不会发送请求到服务器,从而达到减轻服务器访问压力的作用,且由于直接从本地缓存读取资源文件,大大提高了加载速度。
      • 服务器可以通过在响应头里设置Cache-Control: max-age=31536000,max-age代表缓存时间,单位为秒
      • Cache-Control除了max-age外,还可以设置其它属性值:

        no-cache: 不使用强缓存(但仍会使用协商缓存)。
        no-store: 不使用缓存(不使用强缓存也不使用协商缓存),每次都向服务器发送资源请求。
        private: 只允许客户端使用缓存,不允许其他代理服务器进行缓存。
        public: 客户端和代理服务器都可缓存。
        s-maxage: 与max-age类似,区别是s-maxage是设定代理服务器的缓存时间。

      • 使用缓存的话,状态码200后面会标明情况。浏览器缓存资源的地方有两个:磁盘缓存(disk cache)和内存缓存(memory cache)。

        一般来说,浏览器会将较大的资源缓存到disk cache,而较小的资源则被缓存到memory cache里。内存缓存与磁盘缓存相比,访问速度要更快一些!

      • 强缓存除了使用Cache-Control实现之外,还可以使用Expires字段,缺点是依赖本地时间,可以被篡改,Expires是Http1.0规范,Cache-Control是Http1.1规范,
      • Cache-control的优先级要高于Expires,如果两者同时设置,会优先使用Cache-control而忽略掉Expires。
      1. 协商缓存
        • 在强缓存里,是否使用缓存是由浏览器来确定的,而协商缓存则是由服务器来告诉浏览器是否使用缓存资源,也就是浏览器每一次都要发送请求到服务器询问是否使用缓存
        • 浏览器初次请求资源,服务器返回资源,同时生成一个Etag值携带在响应头里返回给浏览器,当浏览器再次请求资源时会在请求头里携带If-None-Match,值是之前服务器返回的Etag的值,服务器收到之后拿该值与资源文件最新的Etag值做对比。
          1. 如果没有变化则返回304,告诉浏览器继续使用缓存(不返回资源文件)。
          2. 如果发生变化,则返回200和最新的资源文件给浏览器使用。
        • 除了Etag外,还有一个Last-Modified的属性,是一个时间值,它是Http1.0规范的,服务器返回Last-Modified,浏览器请求头对应携带的是If-Modified-since。
        • 相比Last-Modified,Etag优先级更高,使用上也更精确一些,因为有时候会存在文件内容并没有改变,但文件的修改时间变更了,Last-Modified不一致所以服务器会重新返回资源文件,实际上还是可以继续使用缓存的。
      • 总结
        • 强缓存优先级大于协商缓存,即两者同时存在时,如果强缓存开启且在有效期内,则不会走协商缓存。
          -强缓存就是浏览器本地根据服务器设置的过期时间来判断是否使用缓存,未过期则从本地缓存里拿资源,已过期则重新请求服务器获取最新资源。
        • 协商缓存则是浏览器本地每次都向服务器发起请求,由服务器来告诉浏览器是从缓存里拿资源还是返回最新资源给浏览器使用。
  • 使用 CDN(内容分发网络)

    • 用户与服务器的物理距离对响应时间也有影响。
    • 内容分发网络(CDN)是一组分散在不同地理位置的 web 服务器,用来给用户更高效地发送内容。典型地,选择用来发送内容的服务器是基于网络距离的衡量标准的。例如:选跳数(hop)最少的或者响应时间最快的服务器。
  • 压缩响应

    • 压缩组件通过减少 HTTP 请求产生的响应包的大小,从而降低传输时间的方式来提高性能。从 HTTP1.1 开始,Web 客户端可以通过 HTTP 请求中的 Accept-Encoding 头来标识对压缩的支持(这个请求头会列出一系列的压缩方法)
    • 如果 Web 服务器看到请求中的这个头,就会使用客户端列出的方法中的一种来压缩响应。Web 服务器通过响应中的 Content-Encoding 头来告知 Web 客户端使用哪种方法进行的压缩
    • 目前许多网站通常会压缩 HTML 文档,脚本和样式表的压缩也是值得的(包括 XML 和 JSON 在内的任何文本响应理论上都值得被压缩)。但是,图片和 PDF 文件不应该被压缩,因为它们本来已经被压缩了。
  • 使用多个域名

    • Chrome 等现代化浏览器,都会有同域名限制并发下载数的情况,不同的浏览器及版本都不一样,使用不同的域名可以最大化下载线程,但注意保持在 2~4 个域名内,以避免 DNS 查询损耗。
  • 避免图片src为空

    • 虽然 src 属性为空字符串,但浏览器仍然会向服务器发起一个 HTTP 请求:
    • IE 向页面所在的目录发送请求;Safari、Chrome、Firefox 向页面本身发送请求;Opera 不执行任何操作。

页面渲染优化

Webkit 渲染引擎渲染流程:
1. 处理 HTML 并构建 DOM 树
2. 处理 CSS 构建 CSS 规则树(CSSOM)
3. DOM Tree 和 CSSOM Tree 合成一棵渲染树 Render Tree。
4. 根据渲染树来布局,计算每个节点的位置
5. 调用 GPU 绘制,合成图层,显示在屏幕上

  • 避免css阻塞

    • css影响renderTree的构建,会阻塞页面的渲染,因此应该尽早(将 CSS 放在 head 标签里)和尽快(启用 CDN 实现静态资源加载速度的优化)的将css资源加载
  • 降低css选择器的复杂度

    浏览器读取选择器,遵循的原则是从选择器的右边到左边读取。

    1. 减少嵌套:最多不要超过三层,并且后代选择器的开销较高,慎重使用
    2. 避免使用通配符,对用到的元素进行匹配即可
    3. 利用继承,避免重复匹配和定义
    4. 正确使用类选择器和id选择器
  • 避免使用CSS 表达式

    • css 表达式会被频繁地计算。
  • 避免js阻塞

    • js可以修改CSSOM和DOM,因此js会阻塞页面的解析和渲染,并且会等待css资源的加载。也就是说js会抢走渲染引擎的控制权。所以我们需要给js资源添加defer或者async,延迟js脚本的执行。
  • 使用外链式的js和css

    • 在现实环境中使用外部文件通常会产生较快的页面,因为 JavaScript 和 CSS 有机会被浏览器缓存起来。对于内联的情况,由于 HTML 文档通常不会被配置为可以进行缓存的,所以每次请求 HTML 文档都要下载 JavaScript 和 CSS。所以,如果 JavaScript 和 CSS 在外部文件中,浏览器可以缓存它们,HTML 文档的大小会被减少而不必增加 HTTP 请求数量。
  • 使用字体图标 iconfont 代替图片图标

    • 图片会增加网络请求次数,从而拖慢页面加载时间
    • iconfont可以很好的缩放并且不会添加额外的请求
  • 首屏加载优化

    • 使用骨架屏或者动画优化用户体验
    • 资源按需加载,首页不需要的资源延迟加载
  • 减少重绘和回流

    • 增加多个节点使用documentFragment:不是真实dom的部分,不会引起重绘和回流
    • 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局);opacity 代替 visiability,visiability会触发重绘(paint),但opacity不会。
    • 把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow),然后你修改 100 次,然后再把它显示出来

JS优化

  • 使用事件委托
  • 防抖和节流
  • 尽量不要使用JS动画
    • css3动画和canvas动画都比JS动画性能好
  • 多线程
    • 复杂的计算开启webWorker进行计算,避免页面假死
  • 计算结果缓存
    • 减少运算次数,比如vue中的computed

图片优化

  • 雪碧图
    • 借助减少http请求次数来进行优化
  • 图片懒加载
    • 在图片即将进入可视区域的时候进行加载(判断图片进入可视区域)
      • IntersectionObserver 的API
const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
     if (entry.isIntersecting) {   
       // console.log('元素进入视口');
     } else {
       // console.log('元素离开视口');
     }
   });
 });
 
 // 添加监听,targetElement监听的目标元素
 observer.observe(targetElement);
 // 要取消观察的目标
 IntersectionObserver.unobserve(targetElement);
  • 使用CSS3代替图片
    • 有很多图片使用 CSS 效果(渐变、阴影等)就能画出来,这种情况选择 CSS3 效果更好
  • 图片压缩
    • 压缩方法有两种,
      1. 通过在线网站进行压缩
      1. 通过 webpack 插件 image-webpack-loader。它是基于 imagemin 这个 Node 库来实现图片压缩的。
  • 使用渐进式jpeg
    • 使用渐进式jpeg,会提高用户体验 参考文章
  • 使用 webp 格式的图片
    • webp 是一种新的图片文件格式,它提供了有损压缩和无损压缩两种方式。在相同图片质量下,webp 的体积比 png 和 jpg 更小。

webpack打包优化

  • 缩小loader 匹配范围
    • 优化loader配置
    • test、include、exclude三个配置项来缩⼩loader的处理范围
    • 推荐include
include: path.resolve(__dirname, "./src"),
  • 抽离css
    • 借助mini-css-extract-plugin:本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载
  • 代码压缩
    1. JS代码压缩
      • mode:production,使用的是terser-webpack-plugin
    2. CSS代码压缩
      • css-minimizer-webpack-plugin
    3. Html文件代码压缩
      • html-webpack-plugin和html-minifier-terser
  • 文件大小压缩
    • 对文件的大小进行压缩,减少http传输过程中宽带的损耗
  • 图片压缩
    • 一般来说在打包之后,一些图片文件的大小是远远要比 js 或者 css 文件要来的大,所以图片压缩较为重要
module: {
  rules: [
    {
      test: /.(png|jpg|gif)$/,
      use: [
        {
          loader: 'file-loader',
          options: {
            name: '[name]_[hash].[ext]',
            outputPath: 'images/',
          }
        },
        {
          loader: 'image-webpack-loader',
          options: {
            // 压缩 jpeg 的配置
            mozjpeg: {
              progressive: true,
              quality: 65
            },
            // 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
            optipng: {
              enabled: false,
            },
            // 使用 imagemin-pngquant 压缩 png
            pngquant: {
              quality: '65-90',
              speed: 4
            },
            // 压缩 gif 的配置
            gifsicle: {
              interlaced: false,
            },
            // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
            webp: {
              quality: 75
            }
          }
        }
      ]
    },
  ]
} 
  • Tree shaking 去除死代码
    • Tree Shaking 是一个术语,在计算机中表示消除死代码,依赖于ES Module的静态语法分析(不执行任何的代码,可以明确知道模块的依赖关系)
  • 代码分离
    • 将代码分离到不同的bundle中,之后我们可以按需加载,或者并行加载这些文件
    • 默认情况下,所有的JavaScript代码(业务代码、第三方依赖、暂时没有用到的模块)在首页全部都加载,就会影响首页的加载速度
    • 代码分离可以分出更小的bundle,以及控制资源加载优先级,提供代码的加载性能
    • 这里通过splitChunksPlugin来实现,该插件webpack已经默认安装和集成,只需要配置即可
    • 默认配置中,chunks仅仅针对于异步(async)请求,我们可以设置为initial或者all
      splitChunks主要属性有如下:
module.exports = {
    ...
    optimization:{
        splitChunks:{
            chunks:"all"
        }
    }
}

配置如下:
Chunks,对同步代码还是异步代码进行处理
minSize: 拆分包的大小, 至少为minSize,如何包的大小不超过minSize,这个包不会拆分
maxSize: 将大于maxSize的包,拆分为不小于minSize的包
minChunks:被引入的次数,默认是1

  • 多线程打包提升打包速度
    • happypack
const HappyPack = require('happypack'); 
const os = require('os'); 
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length }); 
module.exports = { 
  // ... 
   module: { 
       rules: [ 
          { 
             test: /\.js$/, 
             use: { 
               loader: 'happypack/loader', 
               options: { id: 'js' } 
             } 
          }
        ] 
	}, 
    plugins: [ 
 	  new HappyPack({ 
        id: 'js', 
        threadPool: happyThreadPool, 
        loaders: ['babel-loader'] 
      }) 
    ] 
 };
- thread-loader 

vue优化

  • v-for添加key
  • 路由懒加载
    • import引入
  • 第三方插件按需引入
  • 合理使用computed和watch
    • 缓存依赖
    • 实时监听
  • v-for的同时避免使用v-if
  • destory时销毁事件:比如addEventListener添加的事件、setTimeout、setInterval、bus.$on绑定的监听事件等

react优化

  1. map循环展示添加key
  2. 路由懒加载
  3. 第三方插件按需引入
  4. 使用scu,memo或者pureComponent避免不必要的渲染
  5. 合理使用useMemo、memo、useCallback

    他们三个的应用场景都是缓存结果,当依赖值没有改变时避免不必要的计算或者渲染。

    • useCallback 是针对函数进行“记忆”的,当它依赖项没有发生改变时,那么该函数的引用并不会随着组件的刷新而被重新赋值。当我们觉得一个函数不需要随着组件的更新而更新引用地址的时候,我们就可以使用 useCallback 去修饰它。
    • React.memo 是对组件进行 “记忆”,当它接收的 props 没有发生改变的时候,那么它将返回上次渲染的结果,不会重新执行函数返回新的渲染结果。
    • React.useMemo是针对 值计算 的一种“记忆“,当依赖项没有发生改变时,那么无需再去计算,直接使用之前的值,对于组件而言,这带来的一个好处就是,可以减少一些计算,避免一些多余的渲染。当我们遇到一些数据需要在组件内部进行计算的时候,可以考虑一下 React.useMemo

二、webworker中为什么能提升js执行的性能

Web Worker 为 JavaScript 创造了多线程环境,允许 JS 主线程创建 Worker 子线程,将一些任务分配给后者运行。这样做就能充分发挥多核 CPU 主机的优势,让两个线程并行执行
1. 独立线程:每个 Web Worker 运行在自己的线程中,拥有独立的 JavaScript 执行环境,不会阻塞主线程。
2. 消息传递:主线程和 Web Worker 之间通过消息传递进行通信。主线程可以向 Web Worker 发送消息,Web Worker 可以向 主线程发送消息。这种通信是异步的,不会阻塞任何线程。
3. 无 DOM 访问:Web Workers 无法直接访问主线程中的 DOM 元素,因为它们在不同的上下文中运行。

  • 使用场景:

    • 图像处理和滤镜应用
    • 数据分析和计算
    • 实时通信和聊天应用
    • 大规模数据可视化
    • 异步加载资源,如脚本和样式表
  • 在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅, Worker 线程会在计算任务完成时,通过特定的通信方式将结果返回给主线程。

  • 注意: Worker 子线程是浏览器开的,完全受主线程控制。即 Web Worker 是浏览器提供的,JS 并不提供,JS 还是单线程的

// 在主线程和myworker内都是通过postMessage()方法发送数据,监听message事件接收数据
// 主线程内
var myWorker = new Worker('work.js');
myWorker.onmessage = function (event) { // 接收来自子线程内部的数据
  console.log('Received message ' + event.data);
  doSomething();
}
const dataToProcess = [1, 2, 3, 4, 5];
myWorker.postMessage(dataToProcess); // 向`myworker`内部发送数据

// myWorker文件内容,子线程
addEventListener('message', function (e) {  // 接收来自主线程数据
  const result = processData(e.data); // 调用方法,移交处理数据的逻辑
  postMessage(result);   // 将处理的好结果返回给主线程
}, false);  // false指定事件句柄在冒泡阶段执行

function processData(data) {
  // 处理数据的逻辑
  return data.map(item => item * 2);
}

三、微前端

  • 为什么选择微前端

    • 技术栈无关
      • 主框架不限制接入应用的技术栈,微应用具备完全自主权
    • 独立开发、独立部署
      • 微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
    • 增量升级
      • 在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
    • 独立运行时
      • 每个微应用之间状态隔离,运行时状态不共享
  • 为什么不用iframe

    隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。

    1. url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用
    2. UI 不同步,DOM 结构不共享,想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中
    3. 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果
    4. 慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程
  • 选择qiankun的理由

    1. 成熟稳定:qiankun 是由 Ant Group(蚂蚁金服)团队开发和维护的微前端框架,已经在蚂蚁金服内部和众多大型项目中广泛应用并经过验证。它经过了长期的发展和迭代,具有较高的稳定性和可靠性。

    2. 功能丰富:qiankun 提供了完整的微前端解决方案,包括应用的注册、加载、通信、生命周期管理等功能。它具有独立运行、集成部署、按需加载等特性,可以满足复杂的微前端架构需求。

    3. 灵活性:qiankun 支持多种前端框架(如 React、Vue、Angular)的应用集成,不限制开发团队使用的具体技术栈。它提供了统一的应用接入和管理方式,使得不同团队开发的应用可以无缝集成,实现共享组件和状态管理等。

    4. 性能优化:qiankun 在应用加载和通信方面进行了优化,采用了基于浏览器标准的沙箱隔离机制,避免了应用之间的冲突和影响。它支持应用的按需加载,减少了初始加载时的资源开销,提高了整体性能和用户体验。

    5. 社区支持和生态系统:qiankun 拥有活跃的社区和广泛的生态系统,有大量的文档、教程和示例可供参考。它也得到了开源社区的认可和贡献,可以获得及时的技术支持和问题解答。

  • qiankun的原理

    • registerMicroApps 注册子应用
		import { registerMicroApps, start } from 'qiankun';
		registerMicroApps([
			{
				name: 'vue app',
				entry: 'http://localhost:27272',
				contrainer: '#yourContainer',
				activeRule: '/yourActiveRule'
			}
		])
		
		// 通过 onGlobalStateChange 来通讯
		import { initGlobalState } from 'qiankun';
		const state = {
		    baiduinit: window,
		    abc: 456
		}
		// 初始化通信池
		const actions = initGlobalState(state);
		// 监听通讯池的变化
		actions.onGlobalStateChange((state, prev) => {
		    // state: 变更后的状态; prev 变更前的状态
		    console.log(state, prev);
		});
  • qiankun不足之处
  • 1. 样式隔离

    当我们在主应用中引入了多个子应用时,子应用的样式会互相影响,这是因为子应用的样式是全局的,而 qiankun 默认情况下并没有对子应用的样式进行隔离

    • 解决方案:通过 scoped css 来实现应用的样式隔离
import { start, loadMicroApp } from 'qiankun'
// 方法1:启动添加experimentalStyleIsolation
start({
  sandbox: {
    experimentalStyleIsolation: true,
  }
})

// 方法2:手动添加
loadMicroApp('reactApp', {
  sandbox: {
    experimentalStyleIsolation: true,
  }
})
  • 2. 静态资源引用问题

    静态资源再子应用中相对路径引用,主应用下可能无法读取到

    • 微应用打包之后css中字体和背景图片404
      • 原因是 qiankun 将外链样式改成了内联样式,但是字体文件和背景图片的加载路径是相对路径。 而 css 文件一旦打包完成,就无法通过动态修改 publicPath 来修正其中的字体文件和背景图片的路径
      • 解决方案: 小图base64位,大图上传资源服务器,其他资源同样使用绝对路径引用。
        • 所有图片等静态资源上传至 cdn,css 中直接引用 cdn 地址(推荐)
        • 借助 webpack 的 url-loader 将字体文件和图片打包成 base64(适用于字体文件和图片体积小的项目
  • 3. 通信数据初始化覆盖问题

    使用initGlobalState初始化定义一级属性,已经定义过的数据,注意不要书写为如下

	// initGlobalState() 的写法会覆盖掉已经初始化定义的一级属性
	const { setGlobalState }  = initGlobalState()
  • 解决方案:在统一的位置定义一级属性,将通信方法导出后挂载到window上供全局调用:
	const { setGlobalState }  = initGlobalState({
	  demoData: '',
	  demo2Data: ''
	})
	window.$setGlobalState = setGlobalState
	
	// 需要通信更新更新demoData处调用示例:
	window.$setGlobalState({
	  demoData: 'this is demo'
	})
  • 4. 静态资源跨域问题

    问题:配置的子应用报跨域错误

    • 解决方案:由于 qiankun 是通过 fetch 去获取微应用的引入的静态资源的所以必须要求这些静态资源支持跨域。 如果是自己的脚本,可以通过开发服务端跨域来支持。如果是三方脚本且无法为其添加跨域头,可以将脚本拖到本地,由自己的服务器 serve 来支持跨域。

TypeScript

  • 使用Ts的时候,有什么心得?
    1. 写代码的同时可以发现错误,减少找bug、改bug的时间,提升开发效率
    2. 程序中任何位置的代码都有提示
    3. 代码的可维护性,使得重构代码更加容易
    4. 支持ES语法,优先体验最新的语法
  • Ts类型注解有用过没,是什么?

    在Ts中的常用类型细分两类:JS已有的类型和TS新增的类型

    1. JS已有的类型:number、string、boolean、null、 undefinded、symbol,对象类型Object(包括数组、对象、函数等对象)

    2. TS新增类型

      • 联合类型、组合类型、自定义类型、接口、字面量类型、枚举、void、any等
    3. 函数类型参数和返回值

      • 单独指定参数、返回值类型
      	// 普通函数
      	function fn(num: number, name: string): string {
      		return name + num;
      	}
      	// 箭头函数
      	const fn = (num: number, name: string): string {
      		return name + num;
      	}
      
      • 同时指定参数和返回值,一般为type接口来定义函数
      	type addFn = (num1: number, num2: number) => number;
      	const add:addFn = (num1, num2) => {
      		return num1 + num2;
      	}
      
    4. 函数类型void和undefined

      	// void:没有返回值
      	const fn = (num1: number, num2: number):void => {
      		return;
      	}
      	// 返回的是undefined
      	const fn1 = (num1: number, num2: number):undefined => {
      		return undefined;
      	}
      
    5. 对象类型
      ```
      let person: { name: string } = {
      name: ‘zs’
      }

      		// 使用type
      		type Myobj = {
      			name: string;
      			age: number;
      			sex?: string;
      			sayHi(name: string): void; // 普通函数
      			sayHello: (age: number) =>vold; // 箭头函数
      		}
      		let obj: Myobj = {
      			name: 'zs',
      			age: 18,
      			sayHi(name) {},
      			sayHello: (age) => {  
      				// return;
      			}
      		}
      	```
      
    6. 对象类型 interface(接口) 与 type(别名) (主流推荐type)

    interface只能为对象指定类型,而type可以为任意类型指定别名

    	interface Person {
    		name: string;
    		age: number;
    		sayHi():void;
    	}
    	
    	type Person1 = {
    		name: string,
    		age: number,
    		sayHi: () => void,
    	}
    	 // type联合类型
    	type NumberStr = number | string;
    	 // type组合类型
    	type Person2 = Person1 & { sayHello: (str: string) => void; }
    
    1. 元组类型

    是一类明确的元素类型和个数的数组

    	let tupArr: [number, number] = [1,2]
    
    1. 字面量类型
    	let str = 'zs';
    
    1. 枚举类型
    	enum Sex {
    		Male = 'mael',
    		Female = 'female'
    	}
    	const changeSex = (dir: Sex) => {};
    	changeSex(Sex.Male)
    
    1. any任意类型,一般不用
    2. 推断类型
    	// 假设一个页面中的a标签,应为用getElementById()方法获取能获取任何HTML标签,所以该方法返回类型时HTMLElement,但是这个返回值太宽泛,这是需要使用 as 来添加更加具体的类型,如HTMLAnchorElment
    	const link = doucment.getElementById('#js_link') as HTMLAnchorElement;
    
    1. typeof运算符,同等类型
    	let p = { x: 1, y: 2};
    	function form(point: typeof p) {}
    	form(p)
    
    1. 泛型函数
    	function fn<Type>(value: Type): Type {return value;};
    	function fn2<T>(value: T): T{return value;};
    
    1. 约束泛型函数

    能访问参数中的某个定义类型的属性,必须有约束的类型参数

    	interface MyName {
    		name: string
    	}
    	function fn3<Type extends MyName>(value: Type): Type {
    		return value.name;
    	}
    	fn3({ name: 'zs' });
    	fn3({name: 'ls', age: 18});
    
    1. 内置泛型工具
    	// 1. Partial<Type> 来构造一个类型,将所有属性设置为可选
    	type Props = {
    		id: string,
    		children: number[]
    	}
    	// 设置为可选
    	type Part = Partial<Props>;
    	let p1:Props = {id: '1'};
    	let p2.Part = {age: 18};
    
    	// 2. Readonly<Type> 将所有属性设置只读属性
    	type Props1 = {
    		id: string,
    		readonly children: number[]
    	}
    	let p3:Props1 = {id: '2', children: [1]};
    	p3.id = '4';
    	
    	type ReadonlyProps = Readonly<Props1>;
    	//全部为只读属性
    	let p4:ReadonlyProps = {id: '3', children: [2]}; 
    	p4.id = '5'; // 报错
    
    	// Prick<Type, Keys> 自定义选取类型数据,参数1选择谁的属性,参数2选择哪个属性
    	interface Props3 {
    		id: string,
    		title: string,
    		children: number[]
    	}
    	type PrickProps = Prick<Props3, 'id'|'title'>;
    	// 含有id 或者title
    	let p5:prickProps = {
    		id: '6'
    	}
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值