前端基本功-常见概念(一)

anqier 2019-06-30

前端基本功-常见概念(一) 点这里
前端基本功-常见概念(二) 点这里
前端基本功-常见概念(三) 点这里

1.什么是原型链

当一个引用类型继承另一个引用类型的属性和方法时候就会产生一个原型链。(js高级程序设计)
  • 所有 引用类型 都有一个 __proto__ 属性的隐式原型
  • 所有 函数 都有一个 prototype属性的显式原型
  • 所有 引用类型的 隐式原型,指向其构造函数的 显式原型
  • 当试图得到一个属性或方法时,如果这个对象没有,那么会去他的__proto__(即它构造函数的prototype)中查找
原型链 是针对构造函数的,比如我先创建了一个函数,然后通过一个变量new了这个函数,那么这个被new出来的函数就会继承创建出来的那个函数的属性,然后如果我访问new出来的这个函数的某个属性,但是我并没有在这个new出来的函数中定义这个变量,那么它就会往上(向创建出它的函数中)查找,这个查找的过程就叫做原型链。

2.什么是闭包

有权访问另一个函数作用域中的变量函数。(js高级程序设计)
当一个函数存在对非自身作用域的变量的引用 就产生一个闭包
有权访问另一个作用域的函数就是闭包

闭包三点作用: 创建私有变量;延长变量生命周期;防止全局变量污染

3.什么是作用域

就是函数和变量的可访问范围。

作用域 是针对变量的,特点是:先在自己的变量范围中查找,如果找不到,就会沿着作用域往上找。
只有函数作用域和全局作用域(貌似还有个eval作用域),ES6中新增块级作用域那是后话

函数外声明的变量为全局作用域,函数内可以使用
函数内声明的变量为函数作用域,函数外不可以使用

作用域链:一个自由变量一直往上寻找(定义时的)父级作用域内的变量的过程。

自由变量:当前作用域没有定义的变量

作用域什么时候生成的?

页面加载-->创建window全局对象,并生成全局作用域-->然后生成执行上下文,预解析变量(变量提升),生成全局变量对象;$scope

补充:花括号内声明的变量为块级作用域,只能内部使用,减少全局污染

JavaScript是静态作用域,在对变量进行查询时,变量值由函数定义时的位置决定,和执行时的所处的作用域无关。

4.什么是构造函数

在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数。

5.什么是面向对象

ECMAscript开发的两种模式:

1.面向过程: 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了
2.面向对象(OOP): 面向对象是以功能来划分问题,而不是步骤
  • 面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性的方法的对象。

    但是ECMAscript中没有类的概念!prototype是javascript实现与管理继承的一种机制,也是面向对象的设计思想,可以借助prototype属性,可以访问原型内部的属性和方法。

    通常使用构造函数,当构造函数被实列化后,所有的实例对象都可以访问构造函数的原型(prototype)成员,如果在原型中声明一个成员,所有的实列方法都可以共享它

  • 面向对象编程的基本思想是使用对象,类,继承,封装等基本概念来进行程序设计,达到数据结构化,简单抽象的目的(为什么面向对象)

    优点

    • 易维护
采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的

- 易扩展
开发工作的重用性、继承性高,降低重复工作量。
缩短了开发周期

面向对象的三大特性:继承(子类继承父类,提高复用减少冗余),封装(数据的权限和保密),多态(同一接口的不同实现)
面向对象离不开 类 和 实例 两个概念

6.什么是响应式设计?响应式设计的基本原理是什么?

响应式网站设计(Responsive Web design)是一个网站能够兼容多个终端,而不是为每一个终端做一个特定的版本。
基本原理:是通过媒体查询检测不同的设备屏幕尺寸做处理

页面头部必须有meta声明的viewport。

<meta name=’viewport’ content=”width=device-width, initial-scale=1. maximum-scale=1,user-scalable=no”>

7.什么是高阶函数

  • 函数可以作为参数传递
  • 函数可以作为返回值输出

8.什么是函数式编程?

是指通过复合纯函数来构建软件的过程,它避免了共享的状态、易变的数据、以及副作用。函数式编程是声明式而不是命令式,并且应用程序状态通过纯函数流转。
  • 简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论
  • 它具有以下特性:闭包和高阶函数、惰性计算、递归、函数是"第一等公民"、只用"表达式"

进一步了解

9.css盒模型

盒模型 : margin、padding、border、content
  • 标准盒模型

    width = content
    对应css属性 box-sizing:content-box

  • 怪异盒模型

    width = content + padding + border
    对应css属性 box-sizing:border-box

10.关于跨域

关于跨域,有两个误区:

  1. ✕ 动态请求就会有跨域的问题

✔ 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境

  1. ✕ 跨域就是请求发不出去了

✔ 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。

同源策略具体限制些什么呢?

  1. 不能向工作在不同源的的服务请求数据(client to server)

但是script标签能够加载非同源的资源,不受同源策略的影响。

  1. 无法获取不同源的document/cookie等BOM和DOM,可以说任何有关另外一个源的信息都无法得到 (client to client)

跨域最常用的方法,应当属CORS

如下图所示:

前端基本功-常见概念(一)

只要浏览器检测到响应头带上了CORS,并且允许的源包括了本网站,那么就不会拦截请求响应。

CORS把请求分为两种,一种是简单请求,另一种是需要触发预检请求,这两者是相对的,怎样才算“不简单”?只要属于下面的其中一种就不是简单请求:
(1)使用了除GET/POST/HEAD之外的请求方式,如PUT/DELETE
(2)使用了除Content-Type/Accept等几个常用的http头这个时候就认为需要先发个预检请求,预检请求使用OPTIONS方式去检查当前请求是否安全

代码里面只发了一个请求,但在控制台看到了两个请求,第一个是OPTIONS,服务端返回:

详见阮一峰的跨域资源共享CORS详解

前端基本功-常见概念(一)

第二种常用的跨域的方法是JSONP

JSONP是利用了script标签能够跨域,如下代码所示:

function updateList (data) {
    console.log(data);
}

$body.append(‘<script src=“http://otherdomain.com/request?callback=updateList"></script>');

代码先定义一个全局函数,然后把这个函数名通过callback参数添加到script标签的src,script的src就是需要跨域的请求,然后这个请求返回可执行的JS文本:// script响应返回的js内容为

updateList([{
    name: 'hello'
}]);

由于它是一个js,并且已经定义了upldateList函数,所以能正常执行,并且跨域的数据通过传参得到。这就是JSONP的原理。

小结

跨域分为两种,一种是跨域请求,另一种访问跨域的页面,跨域请求可以通过CORS/JSONP等方法进行访问,跨域的页面主要通过postMesssage的方式。由于跨域请求不但能发出去还能带上cookie,所以要规避跨站请求伪造攻击的风险,特别是涉及到钱的那种请求。

本节参考文章:我知道的跨域与安全

11.http/https

HTTP

超文本传输​​协议(HTTP)是用于传输诸如HTML的超媒体文档的应用层协议。它被设计用于Web浏览器和Web服务器之间的通信,但它也可以用于其他目的。 HTTP遵循经典的客户端-服务端模型,客户端打开一个连接以发出请求,然后等待它收到服务器端响应。 HTTP是无状态协议,意味着服务器不会在两个请求之间保留任何数据(状态)。

HTTP是明文传输的,也就意味着,介于发送端、接收端中间的任意节点都可以知道你们传输的内容是什么。这些节点可能是路由器、代理等。

举个最常见的例子,用户登陆。用户输入账号,密码,采用HTTP的话,只要在代理服务器上做点手脚就可以拿到你的密码了。

用户登陆 --> 代理服务器(做手脚)--> 实际授权服务器

在发送端对密码进行加密?没用的,虽然别人不知道你原始密码是多少,但能够拿到加密后的账号密码,照样能登陆。

HTTP是应用层协议,位于HTTP协议之下是传输协议TCP。TCP负责传输,HTTP则定义了数据如何进行包装。

HTTPS

HTTPS相对于HTTP有哪些不同呢?其实就是在HTTP跟TCP中间加多了一层加密层TLS/SSL。

神马是TLS/SSL?

通俗的讲,TLS、SSL其实是类似的东西,SSL是个加密套件,负责对HTTP的数据进行加密。TLS是SSL的升级版。现在提到HTTPS,加密套件基本指的是TLS。

传输加密的流程

原先是应用层将数据直接给到TCP进行传输,现在改成应用层将数据给到TLS/SSL,将数据加密后,再给到TCP进行传输。

HTTPS是如何加密数据的

对安全或密码学基础有了解的同学,应该知道常见的加密手段。一般来说,加密分为对称加密、非对称加密(也叫公开密钥加密)

HTTPS与HTTP的一些区别

  • HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。
  • HTTP协议运行在TCP之上,所有传输的内容都是明文,内容可能会被窃听。HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。
  • HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。
  • 不验证通信方的身份,通信方的身份有可能遭遇伪装。
  • 无法证明报文的完整性,报文有可能遭篡改。

前端基本功-常见概念(一)

使用SPDY加快你的网站速度

谷歌推行一种协议(HTTP 之下SSL之上[TCP]),可以算是HTTP2的前身,SPDY可以说是综合了HTTPS和HTTP两者优点于一体的传输协议,比如

  1. 压缩数据(HEADER)
  2. 多路复用
  3. 优先级(可以给请求设置优先级)

SPDY构成图:

前端基本功-常见概念(一)

SPDY位于HTTP之下,TCP和SSL之上,这样可以轻松兼容老版本的HTTP协议(将HTTP1.x的内容封装成一种新的frame格式),同时可以使用已有的SSL功能。

HTTP2

HTTP2.0可以说是SPDY的升级版(其实原本也是基于SPDY设计的),但是,HTTP2.0 跟 SPDY 仍有不同的地方,主要是以下两点

  • HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
  • HTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATE

http2 新特性

  • 新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
  • 多路复用(MultiPlexing),支持单个连接多次请求,即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
  • header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
  • 服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。目前,有大多数网站已经启用HTTP2.0,例如YouTuBe,淘宝网等网站,利用chrome控制台可以查看是否启用H2:
chrome=>Network=>Name栏右键=>√Protocol

本节参考文章:简单比较 http https http2HTTPS科普扫盲帖

12.GET/POST

  1. GET在游览器回退会刷新,而POST会再次提交请求
  2. GET请求会被游览器主动缓存,而POST不会,除非手动设置
  3. GET请求参数会被完整的保留在游览器历史记录里,而POST中的参数不会被保留
  4. GET产生的URL地址可以被收藏,而POST不可以
  5. GET参数通过URL传递,而POST放在Request body
  6. GET请求只能进行URL编码,而POST支持多种编码方式
  7. GET请求在URL中传递的参数是有长度限制的,而POST没有限制
  8. GET请求会把参数直接暴露在URL上,相比POST更安全
  9. 对参数的数据类型,GET只接受ASCII字符,而POST没有限制
1.请求参数:get参数附在URL后面?隔开,POST参数放在包体中
2.大小限制:GET限制为2048字符,post无限制
3.安全问题:GET参数暴露在URL中,不如POST安全
4.浏览器历史记录:GET可以记录,POST无记录
5.缓存:GET可被缓存,post无
6.书签:GET可被收藏为书签,post不可
7.数据类型:GET只能ASCII码,post无限制

13.MVC/MVVM

MVC

MVC是一种设计模式,它将应用划分为3个部分:数据(模型)、展示层(视图)和用户交互层。结合一下下图,更能理解三者之间的关系。

前端基本功-常见概念(一)

换句话说,一个事件的发生是这样的过程

  1. 用户和应用交互
  2. 控制器的事件处理器被触发
  3. 控制器从模型中请求数据,并将其交给视图
  4. 视图将数据呈现给用户

MVVM

MVVM是Model-View-ViewModel的缩写。mvvm是一种设计思想。Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。

前端基本功-常见概念(一)

在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

  • 在之前的MVC中我们提到一个控制器对应一个视图,控制器用状态机进行管理,如果项目足够大的时候,状态机的代码量就变得非常臃肿,难以维护。
  • 性能问题,在MVC中我们大量的操作了DOM,而大量操作DOM会让页面渲染性能降低,加载速度变慢,影响用户体验。
  • 最后就是当Model频繁变化的时候,开发者就手动更新View,那么数据的维护就变得困难。

为了减小工作量,节约时间,一个更适合前端开发的架构模式就显得非常重要,这时候MVVM模式在前端中的应用就应运而生。

mvvm和mvc区别

mvc和mvvm其实区别并不大。都是一种设计思想。主要就是mvc中Controller演变成mvvm中的viewModel。mvvm主要解决了mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到View 。

3种方式实现MVVM

defineProperty(VUE),脏检查(angular),原生js实现(发布订阅者模式)

  • 在Angular中实现数据的观测使用的是脏检查,就是在用户进行可能改变ViewModel的操作的时候,对比以前老的ViewModel然后做出改变。
  • vue.js 则是采用 数据劫持 结合 发布者-订阅者模式 的方式,通过Object.defineProperty()来劫持各个属性的settergetter,在数据变动时发布消息给订阅者,触发相应的监听回调。

本节参考文章:MVC/MVVM

14.axios优点

  • 同时支持浏览器端和服务端的请求
  • 支持promise
  • 支持请求和和数据返回的拦截
  • 转换请求返回数据,自动转换JSON数据
  • 取消请求
  • 客户端防止xsrf攻击
  • 在node端支持设置代理
  • 内部一些针对具体项目环境的二次封装

本节参考文章:axios优点

15.普通函数/箭头函数

  • 1、当要求动态上下文的时候,就不能够使用箭头函数,箭头函数this的固定化
  • 2、在使用=>定义函数的时候,this的指向是定义时所在的对象,而不是使用时所在的对象
  • 3、不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误
  • 4、不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替
  • 5、不可以使用yield命令,因此箭头函数不能用作Generator函数
class Animal {
    constructor(){
        this.type = 'animal'
    }
    says(say) {
        setTimeout(function () {
            console.log(this.type + 'says' + say)
        },1000)
    }
}
var animal = new Animal()
animal.says('hi') // undefined says hi

我们再来看看=>的情况

class Animal() {
    constructor() {
        this.type = 'animal'
    }
    says(say) {
        setTimeout(() => {
            console.log(this.type + ' says ' + say)
        }, 1000)
    }
}
var animal = new Animal()
animal.says('hi') // animal says hi

本节参考文章:前端面试之ES6篇

相关推荐