前端常见面试题

前端核心技术精讲
本文深入讲解前端开发核心流程,从浏览器解析URL到渲染页面全过程,涵盖缓存、DNS解析、TCP/IP连接、HTTP请求响应机制。同时,解析CSS盒模型、JavaScript闭包、继承、异步编程、模块化技术,探讨HTML5新标签兼容性及WebSocket应用,分享CSS预处理器的高效使用技巧。
 1、浏览器的地址栏输入URL并按下回车。
 2、浏览器查找当前URL是否存在缓存,并比较缓存是否过期。
3、DNS解析URL对应的IP。
4、根据IP建立TCP连接(三次握手)。
5、HTTP发起请求。
6、服务器处理请求,浏览器接收HTTP响应。
7、渲染页面,构建DOM树。
8、关闭TCP连接(四次挥手)
复制代码
flexible
获取dpr和设置dpr的倒数scale
动态生成viewport meta,initial-scale值为scale
设置rem为clientWidth(layoutview port width) 的1 / 10
复制代码
box-sizing : content-box|border-box|inherit;   盒子模型
(1) content-box ,默认值,可以使设置的宽度和高度值应用到元素的内容框。盒子的width只包含内容。
即总宽度=margin+border+padding+width
(2) border-box , 设置的width值其实是除margin外的border+padding+element的总宽度。盒子的width包含border+padding+内容
即总宽度=border+padding+内容

复制代码
闭包是由于内部函数能够访问外部函数的变量造成的。
1、变量作用域
要理解闭包,首先要理解javascript的特殊的变量作用域。
变量的作用域无非就两种:全局变量和局部变量。
function init() {
  var name = 'Mozilla'; // name is a local variable created by init
  function displayName() { // displayName() is the inner function, a closure
    alert(name); // use variable declared in the parent function    
  }
  displayName();    
}
init();
init()创建一个名为的局部变量  name和一个名为的函数displayName()。
该  displayName() 函数是一个内部定义的内部函数,init()仅在init()函数体内可用   
。该  displayName() 函数没有自己的局部变量。
但是,因为内部函数可以访问外部函数displayName()的变量,
  所以可以访问name父函数中声明的变量init()
。但是,displayName() 如果存在相同的局部变量,  则将使用它们。
复制代码
js中继承可以使用原型链prototype
// 父亲类
    function Parent() {
        this.value = 'value';
    }
    Parent.prototype.sayHi = function() {
            console.log('Hi');
        }
        // 儿子类
    function Child() {

    }
    // 改变儿子的prototype属性为父亲的实例
    Child.prototype = new Parent();
    var child = new Child();
    // 首先现在child实例上进行查找,未找到,
    // 然后找到原型对象(Parent类的一个实例),在进行查找,未找到,
    // 在根据__proto__进行找到原型,发现sayHi方法。
    // 实现了Child继承
    child.sayHi();
复制代码
this对象理解,this可以是指单一某个对象,默认是指window对象
new操作符  例:var obj = new Base(); 

该步一共做了三件事:即 
   var obj  = {}; obj.__proto__ = Base.prototype; Base.call(obj);  

第一行,我们创建了一个空对象obj
第二行,我们将这个空对象的__proto__成员指向了Base函数对象prototype成员对象
第三行,我们将Base函数对象的this指针替换成obj。

同步异步  
复制代码
async   

function resolveAfter2Seconds() {
 
 return new Promise(resolve => {
    
setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}


async function asyncCall() {
 
 console.log('calling');
  
var result = await resolveAfter2Seconds();
  
console.log(result);
  /
/ expected output: 'resolved'
}

asyncCall();
复制代码
"同步模式"就是上一段的模式,
后一个任务等待前一个任务结束,然后再执行,
程序的执行顺序与任务的排列顺序是一致的、同步的;
"异步模式"则完全不同,每一个任务有一个或多个回调函数(callback)
,前一个任务结束后,不是执行后一个任务,而是执行回调函数
,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、
异步的。
"异步模式"非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应
,最好的例子就是Ajax操作。在服务器端,"异步模式"甚至是唯一的模式,因为执行环境是单线程的,
复制代码

模块化  (amd cmd)
CommonJS 对模块的定义并不复杂,主要分为模块引用、模块定义和模块标识

模块引用:使用 require 方法来引入一个模块
模块定义:使用 exports 导出模块对象
模块标识:给 require 方法传入的参数,小驼峰命名的字符串、相对路径或者绝对路径

AMD 和 CMD 的差异主要是,前者需要在定义之初声明所有的依赖,后者可以在任意时机动态引入模块。CMD 更接近于 CommonJS
两种规范都需要从远程网络中载入模块,不同之处在于,前者是预加载,后者是延迟加载
复制代码

h5新标签兼容性
IE8/IE7/IE6支持通过document.createElement方法产生的标签,可以利用这一特性让这些浏览器支持HTML5新标签
可以通过js(Modernizr框架的原理是自动检测浏览器是否支持新特性,)监测改浏览器是否支持标签 

websocket兼容低浏览器 
对于低端不支持websocket的浏览器,一般有几个解决方案
使用轮询或长连接的方式实现伪websocket的通信
使用flash或其他方法实现一个websocket客户端 :https://segmentfault.com/q/1010000005000671/a-1020000005003936
https://blog.youkuaiyun.com/u011925826/article/details/17532465
复制代码
 css预处理器赋予了css动态语言的特性,
如变量、函数、运算、继承、嵌套等,有助于更好地组织管理样式文件,
以及更高效地开发项目。css预处理器可以更方便的维护和管理css代码,
让整个网页变得更加灵活可变。对于预处理器,广泛使用的有less和sass。
在这不做对比,2者大同小异,sass基于Ruby语言编写,所以编译sass文件需要Ruby环境。
我们使用sass并不需要过多了解Ruby语言,只需要安装Ruby环境即可,而less则主要是运行在node环境下,功能语法有类似之处。本文主要介绍Ruby下sass的使用。
Mixin 的作用是把重复的代码放到一个类当中,每次只要引用类名,就可以引用到里面的代码了,非常方便。
复制代码
css居中
水平居中
.center {
	width: 960px;
	margin-left: auto;
	margin-right: auto;
}
1. 采用flex布局; 
2. 综合运用line-height、margin与padding; 
3. 综合运用相对定位与绝对定位
复制代码
vue声明周期
Vue提供的可以注册的钩子都在上图片的红色框标注。 他们是:

beforeCreate
在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。

created
实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount
在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
beforeUpdate
数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
该钩子在服务器端渲染期间不被调用。
beforeDestroy
实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
复制代码

vue双向绑定原理

目前几种主流的mvc(vm)框架都实现了单向数据绑定,而我所理解的双向数据绑定无非就是在单向绑定的基础上给可输入元素(input、textare等)添加了change(input)事件,来动态修改model和 view,并没有多高深。所以无需太过介怀是实现的单向或双向绑定。
实现数据绑定的做法有大致如下几种:
发布者-订阅者模式(backbone.js)
脏值检查(angular.js) 
数据劫持(vue.js)
发布者-订阅者模式: 一般通过sub, pub的方式实现数据和视图的绑定监听,更新数据方式通常做法是 vm.set('property', value),这里有篇文章讲的比较详细,有兴趣可点这里
这种方式现在毕竟太low了,我们更希望通过 vm.property = value 这种方式更新数据,同时自动更新视图,于是有了下面两种方式
脏值检查: angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,最简单的方式就是通过 setInterval() 定时轮询检测数据变动,当然Google不会这么low,angular只有在指定的事件触发时进入脏值检测,大致如下:
DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
XHR响应事件 ( $http )
浏览器Location变更事件 ( $location )
Timer事件( $timeout , $interval )
执行 $digest() 或 $apply()
数据劫持: vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
复制代码
vuex

为什么要用vuex?
对于父子组件之前的通信,父组件通过porps传递到子组件,子组件通过$emit发送事件到父组件;父组件还可以通过ref的方式拿子组件的值并共享;
对于组件与组件之间的通信,可以new一个新的Vue实例,专门用来做event bus进行通信
当多个组件之间共享一个状态时,event bus可能就变成乱了
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值