前端面试题四

1. js原型链

 

2. 服务器端怎么设置cookie?

expires

该属性用来设置Cookie的有效期。Cookie中的maxAge用来表示该属性,单位为秒。Cookie中通过getMaxAge()和setMaxAge(int maxAge)来读写该属性。

cookie.setMaxAge(0);//不记录cookie

cookie.setMaxAge(-1);//会话级cookie,关闭浏览器失效

cookie.setMaxAge(60*60);//过期时间为1小时

 

3. Javascript数据类型,Symbol类型一般怎样使用,引用类型和基本类型

基本数据类型:String、Number、null、undefined、Boolean、Symbol、BigInt

应用场景一:我们可以将Symbol用来作为对象属性名(key)

Symbol类型的key是不能通过object.keys()或者for...in来枚举的,它未被包含在对象自身的属性名集合(property names)之中。多以利用该特性,我们可以把一些不需要对外操作或者访问的属性使用Symbol来定义。

也正因为这样的一个特性,我们在使用JSON.stringify()将对象,JSON字符串的时候,Symbol属性你也会排除在输出内容之外。

我们可以利用这一特点来更好的设计我们的数据对象,让“对内操作”和“对外选择性输出”变得更加优雅。

有一些专门的API还是可以取得到Symbol定义的属性的:

然而,这样的话,我们就没办法获取以Symbol方式定义的对象属性了么?非也。还是会有一些专门针对Symbol的API,比如:

// 使用Object的API
Object.getOwnPropertySymbols(obj) // [Symbol(name)]

// 使用新增的反射API
Reflect.ownKeys(obj) // [Symbol(name), 'age', 'title']

应用场景二:使用Symbol来代替常量

const TYPE_AUDIO = 'AUDIO'
const TYPE_VIDEO = 'VIDEO'
const TYPE_IMAGE = 'IMAGE'

使用Symbol之后

const TYPE_AUDIO = Symbol()
const TYPE_VIDEO = Symbol()
const TYPE_IMAGE = Symbol()

应用场景三:使用Symbol来定义类的私有属性/方法

JS中没有Java的private

而有了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')  // true

login.PASSWORD  // oh!no!
login[PASSWORD] // oh!no!
login["PASSWORD"] // oh!no!

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

 

基本类型:string,number,boolean,null,undefined,symbol、bigint

引用类型:Function,Array,Object

 

4. 手写数组去重

利用indexOf去重

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}

利用hasOwnProperty

function unique(arr) {
    var obj = {};
    return arr.filter(function(item, index, arr){
        return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
}

 

5. 讲一下事件流?

(1)事件流描述的是从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序。
(2)事件就是用户或浏览器自身执行的某种动作。诸如click(点击)、load(加载)、mouseover(鼠标悬停)。
(3)事件处理程序响应某个事件的函数就叫事件处理程序(或事件侦听器)。

dom2级事件规定的事件包括三个阶段:事件捕获阶段==>处于目标阶段==>事件冒泡阶段 

洋葱模型

 

6. preventDefault()和stopPropagation()的区别

stopPropagation()阻止事件冒泡

preventDefault()阻止事件默认行为

该方法将通知 Web 浏览器不要执行与事件关联的默认动作(如果存在这样的动作)。例如,如果 type 属性是 "submit",在事件传播的任意阶段可以调用任意的事件句柄,通过调用该方法,可以阻止提交表单。注意,如果 Event 对象的 cancelable 属性是 fasle,那么就没有默认动作,或者不能阻止默认动作。无论哪种情况,调用该方法都没有作用。

 

7. 解决异步的几种方式?
(1)回调函数

function f1(f2){
    setTimeout(function(){
        console.log('先执行 f1')
    },1000)
    f2()
}
function f2() {
    console.log('再执行 f2')
}

总结:回调函数易于实现,便于理解,但多次回调会使得代码高度耦合,回调地狱。

(2)事件监听

脚本的执行不取决代码的顺序,而取决于某一个事件是否发生。

$(document).ready(function(){
     console.log('DOM 已经 ready')
});

  

(3)发布订阅模式

发布/订阅模式是利用一个消息中心,发布者发布一个消息给消息中心,订阅者从消息中心订阅该消息,。类似于 vue 的父子组件之间的传值。

//订阅done事件
$('#app').on('done',function(data){
    console.log(data)
})
//发布事件
$('#app').trigger('done,'haha')

 

(4)promise

Promise 实际就是一个对象, 从它可以获得异步操作的消息,Promise 对象有三种状态,pending(进行中)、fulfilled(已成功)和rejected(已失败)。Promise 的状态一旦改变之后,就不会在发生任何变化,将回调函数变成了链式调用。

export default function getMethods (url){
    return new Promise(function(resolve, reject){
        axios.get(url).then(res => {
            resolve(res)
        }).catch(err =>{
            reject(err)
        })
    })
}

getMethods('/api/xxx').then(res => {
    console.log(res)
}, err => {
    console.log(err)
})

  

(5)generator

Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,使用该对象的 next() 方法,可以遍历 Generator 函数内部的每一个状态,直到 return 语句。

形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式, yield是暂停执行的标记。

next() 方法遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

function *generatorDemo() {
  yield 'hello';
  yield  1 + 2;
  return 'ok';
}

var demo = generatorDemo()

demo.next()   // { value: 'hello', done: false } 
demo.next()   // { value: 3, done: false } 
demo.next()   // { value: 'ok', done: ture } 
demo.next()   // { value: undefined, done: ture } 

  

(6)async/await

async函数返回的是一个 Promise 对象,可以使用 then 方法添加回调函数,async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

await命令后面返回的是 Promise 对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。

async function demo() {
  try {
    await new Promise(function (resolve, reject) {
      // something
    });
  } catch (err) {
    console.log(err);
  }
}

demo().then(data => {
    console.log(data)  // 
})

  

8. defer和async的区别

(1)<script src="script.js"></script>

  没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素读到就加载并执行。

(2)<script async src="script.js"></script>

  有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。

(3)<script defer src="myscript.js"></script>

  有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。

 

 

 9. 写一下双飞翼布局,两边固定中间自适应

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>双飞翼布局</title>
</head>
<style>
  body{
    margin: 0;
    padding: 0;
  }
  #wrapper{
    min-width: 600px;
  }
  #header,#footer{
    width:100%;
    height: 50px;
    line-height: 50px;
    background: yellow;
  }
  #content{
    /* width: 100%; */
    overflow: hidden;
  }
  #left,#right,#middle{
    float:left;
    height: 500px;
  }
  #left{
    margin-left: -100%;
    width: 160px;
    background: orange;
  }
  #middle{
    width: 100%;
    background: pink;
  }
  #right{
    margin-left: -200px;
    width: 200px;
    background: blue;
  }
  #middle-content{
    margin: 0 200px 0 160px;
  }
  
</style>
<body>
  <div id="wrapper">
    <div id="header">header</div>
    <div id="content">
      <div id="middle">
        <div id="middle-content">middle</div>
      </div>
      <div id="left">left</div>
      <div id="right">right</div>
    </div>
    <div id="footer">footer</div>
  </div>
</body>
</html>

10. 移动端适配方式

(1)百分比方案

使用百分比%宽度,高度用px固定,根据可视化区域实时尺寸进行调整,尽可能适应各种分辨率,通常使用max-width/min-width控制尺寸范围过大或者过小。下表是子元素不同属性设置百分比的依据。

优势:原理简单,不存在兼容问题

不足:

  • 如果屏幕尺度跨度太大,相对设计稿过大或者过小的屏幕不能正常显示,在大屏手机或横竖屏切换场景下可能会导致页面元素被拉伸变形,字体大小无法随屏幕大小发生变化。
    ...
  • 设置盒模型的不同属性时,其百分比设置的参考元素不唯一,容易使布局问题变得复杂

(2)rem方案

rem是相对长度单位,rem方案中的样式设计相对于根元素font-size计算值得倍数。

根据屏幕宽度设置html标签的font-size,在布局时使用rem单位布局,达到自适应的目的,是弹性布局的一种实现方式。

  • 兼容性好

不足:不是纯css移动适配方案,需要引入js脚本 在头部内嵌一段 js脚本 监听分辨率的变化来动态改变根元素的字体大小,css样式和 js 代码有一定 耦合性,并且必须将改变font-size的代码放在 css 样式之前。

(3)vh/vw方案

视口是浏览器中用于呈现网页的区域,移动端的视口通常指的是 布局视口

  • vw : 1vw 等于 视口宽度1%
  • vh : 1vh 等于 视口高度 的 **1% **
  • vmin : 选取 vwvh最小 的那个
  • vmax : 选取 vwvh最大 的那个

优势:纯 css 移动端适配方案,不存在脚本依赖问题

不足:存在一些兼容性问题,Android4.4以下不支持

 

(4)rem+vw/vh方案

vw/vh 方案能够实现宽度和高度的自适应,并且逻辑清晰,由于其被支持得较晚,所以存在一定的兼容性问题。将 vw/vh 方案与 rem 方案相结合,给根元素设置随视口变化的vw单位,可以通过postcss-plugin-vwtorem将其转换。具体的计算过程为:

对于1080px宽的设计稿,设置默认根字号的大小为100px,那么设计稿中1px对应的是 100vw/1080 = 0.0925926vw,并且 1rem = 100px,也就可以得到1rem = 9.256926vw

同时可以使用媒体查询限制根元素的最大最小值,实现对页面的最大最小宽度限制,对用户的视觉体验更好。

(5)基于媒体查询的响应式设计

响应式设计 使得一个网站同时适配 多种设备 和 多个屏幕,让网站的布局和功能随用户的使用环境(屏幕大小、输出方式、设备/浏览器能力而变化),使其视觉合理,交互方式符合习惯。如使得内容区块可伸缩与自由排布,边距适应页面尺寸,图片适应比例变化,能够自动隐藏/部分显示内容,能自动折叠导航和菜单。
原理:主要实现是通过 媒体查询,通过给不同分辨率的设备编写不同的样式实现响应式布局,用于解决不同设备不同分辨率之间兼容问题,一般是指PC、平板、手机设备之间较大的分辨率差异。实现上不局限于具体的方案,通常结合了 流式布局 + 弹性布局 方案。比如给小屏幕手机设置@2x图,为大屏手机设置@3x图。
优势:能够使网页在不同设备、不同分辨率屏幕上呈现合理布局,不仅仅是样式伸缩变换
不足:要匹配足够多的设备与屏幕,一个web页面需要多个设计方案,工作量比较大

   通过媒体查询技术需要设置一定量的断点,到达某个断点前后的页面发生显著变化,用户体验不太友好

11. HTTP和HTTPS有什么区别?

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

HTTPS和HTTP的区别主要如下:

(1)https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

(2)http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

(3)http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

(4)http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

12. HTTP状态码

 

 

 

posted @ 2021-08-25 21:49  橱窗  阅读(54)  评论(0编辑  收藏  举报