【前端面经】即时设计

在这里插入图片描述


目录

  • 前言
  • 一面
    • git 常见命令
    • 跨窗口通信
    • vue 响应式原理
    • 发布订阅模式
    • 翻转二叉树
    • Promise.all()
    • 扁平化数组
    • 面试官建议
  • 二面
    • Event Loop 原理
    • Promise 相关
    • css 描边方式
    • requestAnimation
    • React 18 新特性
    • JSX 相关
    • react 输出两次
    • 函数式编程
    • React 批处理机制
    • http请求头有哪些
    • 本地存储
    • 性能优化方面
    • webgl 的优化手段
    • 着色器优化相关
    • 缓冲区和深度测试
    • 异步
    • 原型和原型链
    • 倒序输出
    • 汉语表达
    • 次数最少字符
  • 面试复盘


前言

即时设计 - 可实时协作的专业 UI 设计工具
即时设计是一款可在线编辑的专业UI设计工具,支持原型、交互、智能动画、切图等功能,满足产品创造和交付的全流程体验。
面试题目源码:前端面经

一面

git 常见命令

初始化仓库:git init 
远程仓库地址:git clone / git remote add origin
查看关联的远程仓库列表 git remote -v
显示当前工作目录和暂存区的状态 git status
添加到暂存区 git add .
提交本地仓库 git commit -m "提交日志"
提交日志信息 git log
推送远程仓库 git push origin <本地分支名>
创建分支 git branch 分支名称
切换分支 git checkout 分支名称
合并分支 git merge 分支名称

跨窗口通信

https://juejin.cn/post/7306040473542213644

  • 可以借助 web scoket 通过后端这个载体,进行跨页面通信
  • Broadcast Channel:遵循浏览器的同源策略,基于发布-订阅模式,允许一个窗口发送消息,并由其他窗口接收,本质上是一个数据共享池子
  • SharedWorker:是 HTML5 中提供的一种多线程解决方案,它可以在多个浏览器 TAB 页面之间共享一个后台线程,从而实现跨页面通信
  • 本地化存储 API:利用本地存储实现同域下的数据共享,window 监听 storage 数据变化执行对应的方法回调

vue 响应式原理

  • vue2 使用 Object.defineProperty实现,是 es6 引入的方法,可以通过配置精确添加或修改对象的属性

  • 不能利用 get/set 对额外添加的属性进行监听

  • 不能监听自身数组下标修改元素的变化,直接定义数组可以,但是不常用

  • vue3 使用 Proxy 实现,能够支持对象添加或修改属性的变化

  • 通过reactive() 函数给每一个对象都包一层 proxy,从而实现对数据的监控

  • 支持改变数组的方法,push、pop、shift、unshift、splice、sort、reverse

  • Reflect 是 es6 引入的新特性,提供一种新的方式操作对象

  • 使用 WeakMap 作为缓存区防止对象被重复代理,主要是避免内存泄漏,以及隐藏内部实现细节

发布订阅模式

class PubSub {
  constructor() {
    this.events = {}
  }

  subscribe(event, callback) {
    if (!this.events[event]) this.events[event] = []

    this.events[event].push(callback)
  }
  unSunscribe(event, callback) {
    if (!this.events[event]) return

    this.events[event] = this.events[event].filter((cb) => cb !== callback)
  }
  publish(event, data) {
    if (!this.events[event]) return

    for (let item of this.events[event]) item(data)
  }
}

const pubsub = new PubSub()
function callback1(data) {
  console.log('触发订阅事件 1', data)
}

function callback2(data) {
  console.log('触发订阅事件 2', data)
}

pubsub.subscribe('myEvent', callback1)
pubsub.subscribe('myEvent', callback2)

pubsub.publish('myEvent', '11111')

翻转二叉树

/**
 * 实现翻转二叉树
 * 例如
 *  a
 * / \
 * b c
 * 转为
 *  a
 * / |
 * c b
 */
const invertTree = function (root) {
  if (root === null) return root

  let temp = root.left
  root.left = invertTree(root.right)
  root.right = invertTree(temp)
  return root
}

const ensure = (output, expect, message) => {
  if (JSON.stringify(output) === JSON.stringify(expect)) {
    console.log(`${message} ok`)
  } else {
    console.log(`${message} fail`)
  }
}

const test = function () {
  const input = {
    val: 1,
    left: {
      val: 2,
      left: {
        val: 3,
        left: null,
        right: null,
      },
      right: {
        val: 4,
        left: null,
        right: null,
      },
    },
    right: {
      val: 5,
      left: {
        val: 6,
        left: null,
        right: null,
      },
      right: {
        val: 7,
        left: null,
        right: null,
      },
    },
  }

  const expect = {
    val: 1,
    left: {
      val: 5,
      left: {
        val: 7,
        left: null,
        right: null,
      },
      right: {
        val: 6,
        left: null,
        right: null,
      },
    },
    right: {
      val: 2,
      left: {
        val: 4,
        left: null,
        right: null,
      },
      right: {
        val: 3,
        left: null,
        right: null,
      },
    },
  }

  const output = invertTree(input)
  ensure(output, expect, 'test')
}

// 输出 test ok表示测试成功
test()

Promise.all()

Promise.myAll = function (promises) {
  let result = []
  return new Promise((resolve, reject) => {
    promises.forEach((item, index) => {
      Promise.resolve(item)
        .then((res) => {
          result[index] = res
          if (Object.keys(result).length === promises.length) resolve(result)
        })
        .catch((err) => {
          reject(err)
        })
    })
  })
}

const p1 = Promise.resolve('p1')
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p2 延时一秒')
  }, 3000)
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p3 延时两秒')
  }, 2000)
})

const p4 = Promise.reject(4)

Promise.myAll([p4, p2, p3])
  .then((res) => console.log(res))
  .catch((err) => console.log(err)) // 2秒后打印 [

const promise = new Promise((resolve, reject) => {})
console.log(promise)

扁平化数组

// https://juejin.cn/post/7273693216372916283

console.log('\n --- 一:原生方法 --- \n')
let arr = [1, [2, 3], [4, [5, 6, [7, 8]]]]
console.log(arr.flat()) // 默认解析一层,可以指定参数
console.log(arr.flat(Infinity)) // Infinity完全解析

console.log('\n--- 二、递归解析 ---\n')

function flatten(arr, depth) {
  let result = []
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i]) && depth > 0) {
      result = result.concat(flatten(arr[i], depth - 1))
    } else {
      result.push(arr[i])
    }
  }
  return result
}

console.log(flatten(arr, 1))
console.log(flatten(arr, 2))
console.log(flatten(arr, 3))

console.log('\n--- 三、reduce解析 ---\n')
function reduceFlatten(arr) {
  return arr.reduce((acc, cur) => {
    if (Array.isArray(cur)) {
      return acc.concat(reduceFlatten(cur))
    } else {
      return acc.concat(cur)
    }
  }, [])
}

console.log(reduceFlatten(arr))

面试官建议

  • 面试回答:先总结,然后分点并结合自己的实际项目进行讲解
  • 应届生没有太多的项目/业务经验,面试官可能会重点问一下基础、框架原理、数据结构与算法、计算机网络这些知识点

一面忘记录音了,有一些问题面试后没有回想起来

二面

Event Loop 原理

事件循环(Event Loop)是 JavaScript 中实现异步编程的一种机制。

  1. 执行同步任务,放入调用栈,结果输出到控制台
  2. 异步任务放到web apis,这里分为微任务、宏任务
  3. 同步代码执行完毕(即调用栈清空)启动事件循环机制(Event Loop)
  4. 依次处理执行微任务、宏任务队列,放入调用栈执行

Promise 相关

同步:任务按照次序依次执行,每个任务必须完成后才能执行下一个任务。
异步:异步任务是非阻塞的,可以同时执行多个任务,不需要等待任务的完成。

  • 执行 async 函数,返回的一定是 Promise 对象
  • await 相当于 Promise 的 then
  • try…catch 可捕获异常,代替了 Promise 的 catch
  • promise.all 接收 promises 数组,所有为 resolve 才输出,有一个 reject 就中断输出报
  • promise.allSettled 接收 promises 数组,不论结果是什么,都会输出每一个 promise 的状态

css 描边方式

  • border 普通边框
  • outline 不占用空间和影响元素大小
  • box-shadow 设置阴影描边效果

requestAnimation

  • setTimeout:快速滚动白屏,原因不同设备刷新率不同,setTimout 只是一个固定的时间间隔。只有主线程执行完毕才会检查事件队列的任务,执行时间会变晚
  • requestAnimationFrame:由系统决定回调函数的执行时机,不会引起丢帧现象,1/60 1/75

React 18 新特性

https://juejin.cn/post/7071861718573383716

  • 并发渲染机制,优先处理用户最关心的事情
  • 批处理优化,多个状态合并成一个批次处理,这样可以减少不必要的渲染次数
  • 服务端渲染的改进,引入新的 api createRoot 创建 root 节点
  • 移除对 IE 支持,继续使用需要 17版本

JSX 相关

  • js 是一种动态类型的脚本语言
  • jsx 是 react 的扩展语法,主要用于定义组件UI的结构和外观,最后需要通过构建工具转换为普通的js代码
  • JSX是React的一个语法扩展,它允许你在JavaScript代码中写类似HTML的标记。Babel会将JSX代码转换成普通的JavaScript代码,所有的JSX元素都会被转换成React.createElement函数调用

react 输出两次

  • 组件被开发模式下的严格模式包裹,组件渲染或副作用函数会执行两次,不影响生产模式
  • 函数式编程纯函数的概念,用于帮助开发者发现和修复潜在的问题

函数式编程

总结一下: 函数式编程有两个核心概念。

  • 数据不可变(无副作用): 它要求你所有的数据都是不可变的,这意味着如果你想修改一个对象,那你应该创建一个新的对象用来修改,而不是修改已有的对象。
  • 无状态: 主要是强调对于一个函数,不管你何时运行,它都应该像第一次运行一样,给定相同的输入,给出相同的输出,完全不依赖外部状态的变化。

纯函数带来的意义。

  • 便于测试和优化:这个意义在实际项目开发中意义非常大,由于纯函数对于相同的输入永远会返回相同的结果,因此我们可以轻松断言函数的执行结果,同时也可以保证函数的优化不会影响其他代码的执行。
  • 可缓存性:因为相同的输入总是可以返回相同的输出,因此,我们可以提前缓存函数的执行结果。
  • 更少的 Bug:使用纯函数意味着你的函数中不存在指向不明的 this,不存在对全局变量的引用,不存在对参数的修改,这些共享状态往往是绝大多数 bug 的源头。

React 批处理机制

  • 在事件处理函数的更新不是一个个重新渲染处理的,而是批处理多个状态,将更新操作放入一个队列中,下一段时间一次性执行更新操作
  • 状态更新完成前,一般是无法打印状态的最新值的,只能等到下一次
  • React 的状态更新是异步处理的,可以使用回调函数进行更新

http请求头有哪些

常见请求头:Accept 接受的内容、字符集、编码方式,Content 请求体的类型、长度,缓存机制(强制缓存、协商缓存标识)

本地存储

  • Cookie是在客户端存储数据的机制,用于存储少量用户信息(4KB),可以设置过期时间,基于浏览器。
  • Session是在服务器端存储用户状态的机制,用于存储用户的登录状态和其他相关信息,占用服务器资源,基于服务器。
  • Token是一种无状态的身份验证机制,用于验证用户身份,可以包含用户信息,不占用服务器资源,可以存储在客户端或服务器。
  • IndexedDB 是一个运行在浏览器上的非关系型数据库系统,它允许你存储大量数据,包括文件和二进制数据

性能优化方面

代码层面

  • 使用防抖和节流
  • 减少页面的重排和重绘,要统一调整样式、多次修改 DOM 先脱离标准流
  • 事件触发使用事件委托机制
  • 按需加载,如单页面应用的路由懒加载

构建方面

  • 开启 gzip 压缩代码,vite 使用 vite-plugin-compression 插件,后端开启 gzip 支持
  • 常用的第三库使用 CDN 服务,就是部署多个服务器节点,用户请求将定位到离用户最近的节点

其他

  • 优先使用缓存减少HTTP请求,将多个细小请求可以合并大文件
  • 图⽚优化:对图片进⾏压缩和优化,减少图片的⼤⼩和请求次数
  • 使⽤字体图标:使⽤字体图标可以减少图片的请求,提⾼页面性能
  • 服务端渲染

用户体验

  • 增加骨架屏、loading加载动画效果

webgl 的优化手段

  • 监视渲染帧率、控制台lighthouse性能报告
  • 良好的编码规则,将场景中不需要的对象通过 remove dispose 进行清除废置
  • 使用廉价的灯光,如环境光和平行光
  • 阴影方面:优化阴影贴图范围,降低分辨率贴图尺寸
  • 贴图、模型等资源进行压缩
  • 谨慎使用抗锯齿和后期处理通道
  • 着色器指定精度、保持代码简单、使用贴图纹理表示噪波
  • 尽可能在顶点着色器进行计算,并将结果发送到片元着色器

着色器优化相关

  • 着色器指定精度、保持代码简单、使用贴图纹理表示噪波
  • 尽可能在顶点着色器进行计算,并将结果发送到片元着色器

缓冲区和深度测试

概述:几何体由一个个顶点粒子构成,每个粒子包含了位置、uv贴图(3d=>2d坐标对应)等,三个顶点形成一个面,在three.js中。物体由一个个三角形面构成。
BufferGeometry:是面片、线或点几何体的有效表述。包括顶点位置,面片索引、法相量、颜色值、UV 坐标和自定义缓存属性值。使用 BufferGeometry 可以有效减少向 GPU 传输上述数据所需的开销。目前,three.js的物体都用上了Buffer,可以直接调用,一些顶点可以使用这个。

当WebGL绘制粒子时,WebGL会测试正在绘制的粒子哪个更靠前,在其后面的粒子不会被绘制,在其前面的粒子会被绘制,这被称为深度测试,可以通过alphaTest停用depth testing。

异步

setTimeout(function () {
  console.log(1)
}, 0)

new Promise(function (resolve, reject) {
  console.log(2)

  for (var i = 0; i < 10000; i++) {
    if (i === 10) console.log(10)
    i == 9999 && resolve()
  }

  console.log(3)
}).then(function () {
  console.log(4)
})

console.log(5)

//2 10 3 5 4 1
  • 计时器宏任务,放入宏任务队列
  • new Promise 立即执行函数,输出 2
  • promise 微任务,放入微任务队列
  • 进入 for 循环,输出10 3
  • 同步任务,输出 5
  • 微任务,输出 4
  • 宏任务,输出 1

原型和原型链

function Foo() {
  getName = function () {
    console.log(1)
  }
  return this
}

Foo.getName = function () {
  console.log(2)
}
Foo.prototype.getName = function () {
  console.log(3)
}
var getName = function () {
  console.log(4)
}
function getName() {
  console.log(5)
}

Foo.getName() //2
getName() //4
Foo().getName() //1
new Foo().getName() //3
  • Foo.getName 绑定到类的方法 2
  • var 存在变量提升,function fn1(){} 定义的函数也会变量提升,结果如下
var getName 
function getName() {
  console.log(5)
}

getName = function () {
  console.log(4)
}
//node 环境运行报错、let 声明不可用
  • Foo() 返回 this ,指向window ,但是进行 Foo()函数,getName 被重新赋值了,所以是 1,以后也是1
  • new Foo() 指向当前实例,内部的方法 ,返回3

倒序输出

// 输入:1->2->3->4->5->NULL
// 输出:5->4->3->2->1->NULL

function traverseStr(str) {
  const array = str.split('->').slice(0, -1)
  return array.reverse().join('->') + '->NULL'
}

const target = '1->2->3->4->5->NULL'
const result = traverseStr(target)
console.log(result)

汉语表达

original_84c60a77b6924d3d352c36635ab5963a.png

次数最少字符

const target = 'aaabbbcceeff'
function removeStr(target) {
  let map = new Map(),
    result = []
  for (let ch of target) map.set(ch, (map.get(ch) || 0) + 1)

  let minCount = Math.min(...map.values())

  for (let ch of target) {
    if (map.get(ch) !== minCount) result.push(ch)
  }
  return result.join('')
}

const result = removeStr(target)
console.log(result)

面试复盘

  • 之前面试的一些八股文、总结大部分都在自己内部的语雀文档,后续逐步整理一下发出来,希望能够帮助到面试的小伙伴
  • 大概是12月12号一面,第二天的二面,但是第二轮面试挂了。数字转为汉字那题没写出来,只是说了一下大概的思路(后续源码整理到算法仓库里面),去除出现最少字符虽然写出来了,可能代码逻辑还有待优化的地方
  • webgl 和着色器优化那部分答的一般

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/279674.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

秒杀系统的设计思路(应对高并发,超卖等问题的解决思路)

首先我们先看一下设计秒杀系统时&#xff0c;我们应该考虑的问题。 解决方案&#xff1a; 一.页面静态化结合CDN内容分发 前端把能提前放入cdn服务器的东西都放进去&#xff0c;反正把所有能提升效率的步骤都做一下&#xff0c;减少真正秒杀时候服务器的压力。 秒杀活动的页面…

年度总结和规划

年度总结和规划 目录概述需求&#xff1a; 设计思路实现思路分析1.技术总结2.管理总结3.职业计划比较 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait…

利用F12和Fiddler抓包

网络基础 http 而http协议又分为下面的部分,点击具体条目后可以查看详细信息 http请求消息:请求行(请求方法),请求路径,请求头,请求体(载荷) http响应消息:响应行(响应状态码),响应头&#xff0c;响应体 请求行 即请求方法 get post put patch 响应行 即响应码,常见响应状态…

Java基础02-Java编程基础

文章目录 变量&#xff08;Variables&#xff09;局部变量和成员变量局部变量&#xff08;Local Variables&#xff09;成员变量&#xff08;Instance Variables&#xff09; 标识符&#xff08;Identifiers&#xff09;八种基本数据类型原始数据类型&#xff08;Primitive Dat…

java中如何使用elasticsearch—RestClient操作文档(CRUD)

目录 一、案例分析 二、Java代码中操作文档 2.1 初始化JavaRestClient 2.2 添加数据到索引库 2.3 根据id查询数据 2.4 根据id修改数据 2.4 删除操作 三、java代码对文档进行操作的基本步骤 一、案例分析 去数据库查询酒店数据&#xff0c;导入到hotel索引库&#xff0…

python+django超市进销存仓库管理系统s5264

本次设计任务是要设计一个超市进销存系统&#xff0c;通过这个系统能够满足超市进销存系统的管理及员工的超市进销存管理功能。系统的主要功能包括&#xff1a;首页、个人中心、员工管理、客户管理、供应商管理、承运商管理、仓库信息管理、商品类别管理、由管理员和员工&#…

Metapreter 详细教程--进阶教程

常用命令 基本命令 命令说明sysinfo查看系统信息ls列出目录或文件夹pwd获取当前目录地址cd切换目录&#xff0c;注意这里的win系统需要用用两个反斜杠来分割&#xff08;cd c:\windows\system32 &#xff09;help帮助getuid查看当前用户是谁getpid查看当前进程号ps查看所有进…

API 开放平台项目(已整理,已废弃)

项目大纲 前端 React 18Ant Design Pro 5.x 脚手架Ant Design & Procomponents 组件库Umi 4 前端框架OpenAPI 前端代码生成 后端 Java Spring BootMySQL 数据库MyBatis-Plus 及 MyBatis X 自动生成API 签名认证&#xff08;Http 调用&#xff09;Spring Boot Starter&#…

数据库——简单查询复杂查询

1.实验内容及原理 1. 在 Windows 系统中安装 VMWare 虚拟机&#xff0c;在 VMWare 中安装 Ubuntu 系统,并在 Ubuntu 中搭建 LAMP 实验环境。 2. 使用 MySQL 进行一些基本操作&#xff1a; &#xff08;1&#xff09;登录 MySQL&#xff0c;在 MySQL 中创建用户&#xff0c;…

OpenCV-Python(22):直方图的计算绘制与分析

目标 了解直方图的原理及应用使用OpenCV 或Numpy 函数计算直方图使用Opencv 或者Matplotlib 函数绘制直方图学习函数cv2.calcHist()、np.histogram()等 原理及应用 直方图是一种统计图形&#xff0c;是对图像的另一种解释&#xff0c;用于表示图像中各个像素值的频次分布。直…

机器学习归一化和标准化

1. 为什么做归一化和标准化 样本中有多个特征&#xff0c;每一个特征都有自己的定义域和取值范围&#xff0c;他们对距离计算也是不同的&#xff0c;如取值较大的影响力会盖过取值较小的参数。因此&#xff0c;为了公平&#xff0c;样本参数必须做一些归一化处理&#xff0c;将…

UI演示双视图立体匹配与重建

相关文章&#xff1a; PyQt5和Qt designer的详细安装教程&#xff1a;https://blog.csdn.net/qq_43811536/article/details/135185233?spm1001.2014.3001.5501Qt designer界面和所有组件功能的详细介绍&#xff1a;https://blog.csdn.net/qq_43811536/article/details/1351868…

如何理解李克特量表?选项距离相等+题目权重相等!

在学术研究中&#xff0c;通过开展问卷调查获取数据时&#xff0c;调查问卷分为量表题和非量表题。量表题就是测试受访者的态度或者看法的题目&#xff0c;大多采用李克特量表。 李克特量表是一种评分加总式态度量表&#xff08;attitude scale&#xff09;&#xff0c;由美国…

论文阅读——Slide-Transformer(cvpr2023)

Slide-Transformer: Hierarchical Vision Transformer with Local Self-Attention 一、分析 1、改进transformer的几个思路&#xff1a; &#xff08;1&#xff09;将全局感受野控制在较小区域&#xff0c;如&#xff1a;PVT&#xff0c;DAT&#xff0c;使用稀疏全局注意力来…

山西电力市场日前价格预测【2023-12-28】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-12-28&#xff09;山西电力市场全天平均日前电价为814.30元/MWh。其中&#xff0c;最高日前电价为1500.00元/MWh&#xff0c;预计出现在08:00~08:45,17:00~20:15。最低日前电价为394.61元/…

FairyGUI-Cocos Creator官方Demo源码解读

博主在学习Cocos Creator的时候&#xff0c;发现了一款免费的UI编辑器FairyGUI。这款编辑器的能力十分强大&#xff0c;但是网上的学习资源比较少&#xff0c;坑比较多&#xff0c;主要学习方式就是阅读官方文档和练习官方Demo。这里博主进行官方Demo的解读。 从gitee上克隆项目…

Java多线程<二>多线程经典场景

leetcode 多线程刷题 上锁上一次&#xff0c;还是上多次&#xff1f; 同步的顺序。 1. 交替打印字符 使用sychronize同步锁使用lock锁使用concurrent的默认机制使用volitale关键字 Thread.sleep() / Thread.yield机制使用automic原子类 方式1 &#xff1a;使用互斥访问st…

Linux上管理不同版本的 JDK

当在 Linux 上管理不同版本的 JDK 时&#xff0c;使用 yum 和 dnf 可以方便地安装和切换不同的 JDK 版本。本文将介绍如何通过这两个包管理工具安装 JDK 1.8 和 JDK 11&#xff0c;并利用软连接动态关联这些版本。 安装 JDK 1.8 和 JDK 11 使用 yum 安装 JDK 1.8 打开终端并…

Linux 内存数据 Metrics 指标解读

过去从未仔细了解过使用 free、top 等命令时显式的内存信息&#xff0c;只关注了已用内存 / 可用内存。本文我们详解解读和标注一下各个数据项的含义&#xff0c;同时和 Ganglia 显式的数据做一个映射。开始前介绍一个小知识&#xff0c;很多查看内存的命令行工具都是 cat /pro…

Pytorch框架基础

参考资料 pytorch框架基础 Pycharm 页面卡住解决方案 使用ps命令结合grep来查找PyCharm相关的进程 ps aux | grep pycharm kill -9 [PID]关于怎么找这个卡住的进程&#xff0c;据初步观察&#xff0c;卡住进程打印的信息是最长的&#xff0c;此外&#xff0c;在卡住进程的打…