2024-2-19 字节商业化 二面 过问
自我介绍
项目:odin 低代码
有没有自己封装组件:用的 element 的
画布定位:相对和绝对,放大怎么办?
实习:性能优化、协作方式、需求评审开发
Vue
Vue2 和 Vue3 的区别
响应式,v2 对数组怎么处理的:原型链改写,还深问了是哪些方法。
v3 有哪些 hooks
异步组件了解吗,怎么用
CSS 布局有哪些
flex、grid
了解 sticky 吗? 知道用的不多,所以后面就不怎么问 css 了
Promise 的状态还有方法
TS 了解多少、enum 咋用
setTimeout 一定准嘛,怎么实现精准的
手写模版字符串,思路对,正则不咋熟没写出来
let infos = { name: 'xiaoming', age: 23, city: 'beijing', school: 'PKU',}toTmplString('my name is ${name},I am ${age& ...
JS 中的浅拷贝与深拷贝拷贝数据这是一个很常见的操作,像基本类型我们可以直接赋值,没啥影响 🥳,但如果是引用类型的话,直接赋值是会出问题的,看个小例子:
let obj = { name: '111' }let copyObj = objcopyObj.name = 'copy'console.log(copyObj) // { name: 'copy' }console.log(obj) // { name: 'copy' }
我们可以发现一个很明显的问题,改的是copyObj啊,为啥子原来的obj里面的东东也被改了 😭?
这就涉及到引用类型的存储方式了,引用类型的存储是存储在堆内存中的,而栈内存中存储的是指向堆内存中的地址。所以说,我们上面的赋值就是把地址给了copyObj,他们俩指向的是同一个地址,所以改一个另一个也会被改。
那么我们怎么解决这个问题呢?这就需要了解浅拷贝和深拷贝了 🤗。
浅拷贝浅拷贝指的是只复制对象或数组本身,而不 ...
JS 中的 new前面我们已经学过了 this,原型链了,现在可以来理解 new 做了啥了 🤪。
有啥用先来看例子
function Test(name) { this.name = name}Test.prototype.sayName = function () { console.log(this.name)}const t = new Test('111')console.log(t.name) // '111't.sayName() // '111'
这里我们可以看到,通过 new 生成的实例,可以访问到构造函数中的属性和原型链上的方法。也就是说,new 做了几件事,创建了一个新的对象,将这个对象的原型链指向构造函数的原型对象,并且把构造函数的 this 指向这个新的对象。
返回值问题一般来说,我们用做构造函数时,不会有 return,默认也是 return undefined,但是如果我们手动 return 值会发生什么?
已经有人测试过了 🤗,如果返回的是一个对象 ...
JS 中的原型与原型链这也是 JS 中的一个重要的概念,我个人一直理解他们的作用是为了更好的复用函数。他包含了__proto__ 和 prototype,这两个东西经常让人搞混,这里来看看。
为什么需要他们看个例子:
function Person(name, age) { this.name = name this.age = age this.eat = function () { console.log(age + '岁的' + name + '在吃饭。') }}let p1 = new Person('111', 24)let p2 = new Person('222', 24)console.log(p1.eat === p2.eat) // false
这里我们可以看到,通过new生成的实例,都开了一块新的内存,所以他们的eat函数是不一样的,这就导致了内存的浪费,所以说我们可以用一个共享的地方,让实例可以去这里找到这个函数,这就是原型链的 ...
JS 中的==运算符😡 学 JS 的肯定被==运算符折磨过,他会发生隐式类型转换,而且里面的逻辑也比较复杂,如果面试一问,感觉直接寄 😫。所以这里来看看他到底是个啥机制,至少要能说出来些啥,后面也可以来引出===、Object.is()还有SameValueZero (零值相等)算法探讨 JS 中的相等机制。
宽松相等算法JS 的行为遵循 ES 语言说明书,其中这个==的底层原理定义在IsLooselyEqual(x, y),这个也叫宽松相等算法。
这里直接翻译一下他的定义:
Type(x) === Type(y),return x === y。
x === null && y === undefined,true。
x === undefined && y === null,true。
(兼容一些非 ES 语言的对象)
若 x 是 Object 类型且 x 有一个 [[IsHTMLDDA]] 内部插槽,且 y === undefined || y === null,true。
若 x === undefined || x === null,且 y ...
JS 中的作用域链与闭包前言年前字节一面就被这个坑了,还有闭包也说不出来,当时只能从动态作用域、this 的方面来解释,👉🏻😔
作用域链首先我们先来了解一下作用域链,先看这个代码
var a = '111'function A() { console.log(a) a = '222' function B() { console.log(a) } B()}A()
我想他的输出应该是: 111 222,原因也很简单,因为作用域链,在打印 a 的时候,函数 A 里面没有这个变量,就沿着作用域链网上找到了全局的 a。
那再看这个:
function bar() { console.log(myName)}function foo() { var myName = '111' bar()}var myName = '222'foo()
按照我当时掉入坑的想法,我会认为他输出的是 111,但是实际答案是 2 ...
CSS 布局前言在 CSS 中我们可以给元素添加样式,但是元素之间的排列方式是由布局来决定的。CSS 中也有很多种布局方式,下面了解一下常见的布局方式,不过首先了解俩个概念。
盒子模型页面中的每个元素都可以看作一个盒子,也就叫做盒子模型。
分类W3C 标准盒子模型和IE 怪异盒子模型
如果说指定了width: 100px,那么在 W3C 标准盒子模型中,width指的是内容(content)的宽度,而在 IE 怪异盒子模型中,width指的是内容 + padding + border 的宽度。
box-sizing: content-box; /* W3C 标准盒子模型 */box-sizing: border-box; /* IE 怪异盒子模型 */
获取盒子模型的宽高
offsetWidth:获取盒子模型的宽度,包括content、padding、border。
offsetHeight:获取盒子模型的高度,包括content、padding、border。
clientWidth:获取盒子模型的宽度,包括content、padding,不包括border。
clientHeig ...
手搓简单前端路由前言在学习vue-router的时候我们就有了解过,前端路由的俩中模式:hash 和 history,那么这里我们就分别用这俩种方法来手写实现一个路由看看。
Hash 模式在写之前,我们先了解一下以前 hash 是怎么用的。hash 可以用于页面内锚点定位,比如<a href="#title">title</a>,点击这个链接不会刷新页面,而是浏览器滚动到相应的位置。
其实 Hash 模式就是利用的这个特点,使得 SPA 应用控制路由时,不刷新页面,然后拦截 hash 的变化来切换页面。不过也带来了缺点,无法使用锚点定位了。
所以说我们的目的也就是俩个:
修改 url,并且同时需要保证不刷新页面
监听 url 变化,作出处理
在 hash 模式中,可以通过 a 标签来做到 1,浏览器也提供了onhashchange这个 API 来监听 hash 变化,所以我们可以写出如下代码
不过还有一个问题,刚进入页面时,没有内容,可以添加一个DOMContentLoaded事件处理就可以
<ul> <li> ...
手写 Vue 单双向绑定
代码仓库地址:https://github.com/Juns-g/vue-insights/tree/main/src/%E5%AE%9E%E7%8E%B0%E5%8D%95%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A
前言首先我们得了解这是个啥 🤓。先介绍一下数据驱动视图,可以理解为我们更改了一个数据,对应的展示视图就会自动变化:
<h1>name</h1><script> let name = 'juns' // 这个时候展示应该是 <h1>juns</h1> // ... name = 'other' // 这个时候视图自动改变,变成了<h1>other</h1></script>
也就是说,我们之需要改变数据,对应的视图展示的内容其实就是数据,数据变化时,视图也会自动随之变化。单向绑定就可以理解成这样,我们使用特定语法把一个数据与视图绑定,然后改变数据的时候视图就会自动更新,比如 ...
CSS 基础前言从头开始温习一遍 CSS,然后记录一下,避免以后忘了。
概念选择器选择器,顾名思义就是用来选择 HTML 元素的,不然我们在 CSS 中如何知道应该给哪一个元素添加样式呢?🤗
他分为五类:
元素选择器: 选择一个或多个 dom 元素
关系选择器: 选择元素之间的关系,也叫做运算符
属性选择器: 根据元素的属性来选择对应的元素
伪类选择器: 选择元素的特殊状态
伪元素选择器: 选择元素的特殊部分
元素选择器* { /* 选择所有的元素 */}div { /* 选择所有的 div 元素 */}div#id111 { /* 选择 id 为 id111 的 div 元素 */}span.class1 { /* 选择 class 为 class1 的 span 元素 */}
关系选择器 / 运算符div span { /* 包含 */ /* 选择 div 元素下的所有 span 元素 */}.box > span { /* 只能选中子 ...