面试题解答

413 阅读6分钟

MVVM和MVC模式

Model: 就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应得model。

View: 就是展现出来的用户界面。

基本上,绝大多数软件所做的工作无非就是从数据库存储中读出数据,展现到用户界面上,然后从用户界面接受输入,写入到数据存储里面去。

如何把model展现到view上,以及如何把数据从view写入到model里,不同的人有不同的意见。

  • MVC派的看法:界面上的每个变化都是一个事件,我只需要针对每个事件写一堆代码,把用户的输入转换成model里的对象就行了,这堆代码可以叫controller。
  • MVVM派的看法:给view里面的各个控件也定义一个对应得数据对象,这样,只要修改这个数据对象,view里面显示的内容就自动跟着刷新,而view里面做了任何操作,这个数据对象也跟着自动更新。 所以:

ViewModel: 就是与界面(view)对应得model。因为,数据库结构往往是不能直接跟界面控件一一对应上的,所以,需要再定义一个数据对象专门对应view上的控件。而viewModel的职责就是把model对象封装成可以显示和接受输入的界面数据对象。

至于viewModel的数据跟随着view自动刷新,并且同步到model里去,这部分代码可以写成公共的框架,不用程序员自己操心了。

简单的说,viewModel就是View和Model的连接器,View与Model通过ViewModel实现双向绑定。

实现一下「模版字符串」功能;

es6.ruanyifeng.com/#docs/strin…

实现一下 Promise.all (Promise 不用写);

var p1 = new Promise((resolve,reject)=>{
    setTimeout(resolve(1), 10000)
})
var p2 = new Promise((resolve,reject)=>{
    setTimeout(resolve(2), 20000)
})
var p3 = new Promise((resolve,reject)=>{
    setTimeout(resolve(3), 30000)
})
var p4 = new Promise((resolve,reject)=>{
    throw new Error('123')
    setTimeout(resolve(4), 40000)
})

function promiseAll(arr){
    return new Promise((resolve, reject)=>{
        var resultArr = []
        arr.forEach(p => {
            p.then((value)=>{
                resultArr.push(value)
                if(resultArr.length === arr.length){
                    resolve(resultArr)
                }
            },(reason)=> {
                reject(reason)
            })
        });
    })
    
}

promiseAll([p1,p2,p3,p4]).then((value)=>{
    console.log(value)
},(reason)=>{
    console.log(reason)
})

怎么实现响应式布局的;

  • 媒体查询
  • 百分比
  • rem 相对于根节点html的font-size
  • vw、vh (视图viewport单位)

css flex 的各个属性值;

  1. 容器的6个属性
  • flex-direction: row | row-reverse | column | column-reverse 定义主轴的方向
  • flex-wrap : wrap | no-wrap | wrap-reverse 定义项目的换行方式
  • flex-flow : 默认row nowrap 是flex-direction和flex-wrap的简写
  • justify-content:flex-start | flex-end | space-between | space-around | center 定义项目在主轴对齐方式
  • align-items : flex-start | flex-end | center | baseline | stretch 定义项目在交叉轴对齐方式
  • align-content: flex-start | flex-end | center | space-between | space-around | stretch 定义很多根轴线的对齐方式。
  1. 项目的6个属性
  • order : 定义项目的排序顺序。数值越小,排列越靠前,默认为0。
  • flex-grow:定义项目的放大比例,默认是0,即存在剩余空间也不放大。
  • flex-shrink:定义项目的缩小比例,默认为1,即如果存在项目不足,该项目将缩小。
  • flex-basis:定义了项目占据的固定空间,默认auto
  • flex: flex-grow、flex-shrink和flex-basis的简写,默认值是0 1 auto
  • align-self:auto | flex-start | flex-end | center | baseline | stretch 定义单个项目与其他项目不一样的对齐方式,可覆盖align-items,默认为auto

css 动画 animation 各个时间值含义;

  • @keyframes 为动画指定一些关键帧,关键帧包含元素在特定时间所拥有的样式。
  • animation-name 规定需要绑定到选择器的keyframe名称。
  • animation-duration 规定完成动画所花费的时间,以秒或毫秒计。
  • animation-timing-function 规定动画的速度曲线。
  • animation-delay 规定在动画开始之前的延迟。
  • animation-iteration-count 规定动画应该播放的次数。
  • animation-direction 规定是否应该轮流反向播放动画。

css 如何实现让一个元素旋转并横向移动,如果只用一个 css 属性;

transform:

less 与 sass 区别,技术选型时如何取舍;

ES6 symbol 如何使用以及使用场景;

原文链接:blog.csdn.net/celi_echo/a…

  1. 使用Symbol来作为对象属性名(key)
  • Symbol类型的key是不能通过Object.keys()或者for...in来枚举的,它未被包含在对象自身的属性名集合之中。所以,利用该特性,我们可以把一些不需要对外操作和访问的属性使用Symbol来定义。
  • 也是因为这样的特性,当使用JSON.stringify()将对象转化为JSON字符串的时候,Symbol属性也会被排除在输出内容之外。
  • 我们可以利用这一特点来更好的设计我们的数据对象,让“对内操作”和“对外选择性输出”变得更加优雅。
  • 我们如何获取以Symbol方式定义的对象属性呢?
// 1. 使用Object的API 
Object.getOwnPropertySymbols(obj) //[Symbol(name)]
// 2. 使用新增的反射API 
Reflect.ownKeys(obj) 
  1. 使用Symbol来代替常量
const PENDING = Symbol();
const ONFULFILLED = Symbol();
const ONREJECTED = Symbol();
  1. 使用Symbol定义类的私有属性、方法
  • 在JavaScript中,是没有如java等面向对象语言的访问控制关键字private的,类上面定义的属性或方法都是可公开访问的。这对我们进行API设计时造成一些困扰。

  • 而有了Symbol以及模块化机制,类的私有属性和方法才变成可能,例如:

  • 在文件a.js中

const PASSWORD = Symbol();
class Login {
    constructor(username, password) {
        this.username = username;
        this[PASSWORD] = password;
    }
    checkPassword(pwd) {
        return this[PASSWORD] === pwd
    }
}
export default Login;
  • 在文件b.js中
import Login from './a'
const login = new Login('admin', '123456');
login.checkPassword('123456')

由于Symbol常量PASSWORD被定义在a.js所在的模块中,外面的模块获取不到这个Symbol,也不可能再创建一个一模一样的Symbol出来(因为Symbol是唯一的),因此这个PASSWORD的Symbol只能被限制在a.js内部使用,所以使用它来定义的类属性是没有办法被模块外访问的,达到了一个私有化的效果。

ES6 Proxy 如何使用以及使用场景,说说 Reflect;

参考文章: blog.flqin.com/371.html

  • proxy代理
  • 使用场景1:vue3的数据劫持就是基于proxy实现的
  • 使用场景2:实现一个私有变量,外部只能调用不能修改
let obj = {
    a: 1,
    b: 2
}
new Proxy(obj, {
    
})

generator 有什么应用场景;

  • generator返回一个迭代器
  1. 部署Iterator接口 利用Generator函数,可以在任意对象上部署Iterator接口
function* iterEntries(obj){
    let keys = Object.keys(obj);
    for(let i=0; i<keys.length; i++){
        let key = keys[i];
        yield [key, obj[key]]
    }
}

let myObj = { foo : 3, bar : 7}

for(let [key, value] of iterEntries(myObj)){
    console.log(key, value)
}

async await 如何实现的;

  • async await是generator的语法糖;
  • async相当于function * ;
  • await相当于yield;
  • 内置迭代器
  1. git reset 与 revert 区别,revert 多个 mr 改如何处理;
  2. git 如何撤回 add 后的内容;

http2 与 http1.1 区别,了解 http3 么,说说;

http2 多路复用、服务器推送

tcp 与 udp 的区别;

  • tcp和udp都是传输层的协议;
  • tcp是面向连接的、可靠的传输协议
  • udp是无连接、不可靠的传输协议
  • udp比tcp传输速度快,适合实时性高、如视频播放、在线聊天
  • tcp通过三次握手、超时重传、快重传、慢启动、分包、确认应答等机制保证传输的可靠性。