目录

require() 加载文件机制

线程和进程

线程

单线程

Nodejs的线程与进程

网络模型

初识 TCP 协议

三次握手

I/O

I/O 先修知识

阻塞与非阻塞 I/O

同步与异步 I/O

Git

基础命令

分支操作

修改远程仓库地址

远程分支获取最新的版本到本地

拉取远程仓库指定分支到本地

SEO优化

优化策略

SEO实战

TDK优化

页面内容优化

使用html5结构

唯一的H1标题

img设置alt属性

nofollow

正文

URL优化

URL静态化

URL规范化

robots

robots.txt

meta robots

sitemap

SEO工具

let、const、class和var的区别

js三大事件(鼠标事件、键盘事件、html事件)

鼠标事件

键盘事件

HTML事件

JS引擎的执行机制

首先,请牢记2点:

3.JS中的event loop(2)

4. 谈谈setTimeout

webpack

DOCTYPE

严格模式与混杂模式如何区分?它们有何意义?

get和post的区别

h5新特性

语义化标签

标签新属性

细说data-* dataset(IE11,火狐谷歌)

classList(火狐谷歌最新,IE10以上)

HTML5新表单

新的input类型

新的form属性

新的input属性

音频(audio)和视频(video)

支持的格式和写法

标签属性

方法

事件

事件属性

css3新特性

过渡

动画

形状转换

选择器

阴影

边框

边框图片

边框圆角

background-size

文字

换行

超出省略号

多行超出省略号

颜色

rgba

hsla

渐变

弹性布局——flex

盒模型定义

媒体查询

 伪类与伪元素

mongodb

为什么要用MongoDB

几个shell实操

Mongobd的重要模块–GridFS

GridFS存储原理

深入浅出mongoose

小程序

响应的数据绑定

页面管理

基础组件

丰富的 API

云开发

js 深拷贝 vs 浅拷贝

堆和栈的区别

对象

数组

浏览器的兼容性

Web标准以及W3C

主流浏览器的内核

 标准模式(Standards Mode)和怪异模式 (Quirks Mode)

CSS盒模型

重置浏览器样式

表现与数据分离

HTML语义化

CSS选择器优先级

清除浮动

响应式布局和自适应布局详解

响应式布局概念

响应式设计的步骤

一些注意的

rem是如何实现自适应布局的?

rem是什么?

为什么web app要使用rem?

1、实现强大的屏幕适配布局:

2.固定宽度做法

3.响应式做法

4.设置viewport进行缩放

rem能等比例适配所有屏幕

REM自适应JS

响应式与自适应的区别

 JavaScript 数据类型知识整理

javascript中有哪些数据类型

基本类型

对象类型

说说你对javascript是弱类型语言的理解?

javascript中强制类型转换是一个非常易出现bug的点,知道强制转换时候的规则吗?

ToPrimitive(转换为原始值)

toString

valueOf

强制转换

Number()

String()

Boolean()

js转换规则不同场景应用

什么时候自动转换为string类型

什么时候自动转换为Number类型

什么时候进行布尔转换

抽象相等

js中的数据类型判断

typeof

instanceof

NaN相关总结

NaN的概念

什么时候返回NaN (开篇第二道题也得到解决)

对 null 和 undefined 进行比较

奇怪的结果:null vs 0

特立独行的 undefined

规避错误

误区

toString和String的区别


 

require() 加载文件机制

当 Node 遇到 require(X) 时,按下面的顺序处理。

(1)如果 X 是内置模块(比如 require('http'))
  a. 返回该模块。
  b. 不再继续执行。

(2)如果 X 以 "./" 或者 "/" 或者 "../" 开头
  a. 根据 X 所在的父模块确定 X 的绝对路径
  b. 将 X 当成文件,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。

  • X
  • X.js
  • X.json
  • X.node

  c. 将 X 当成目录,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。

  • X/package.json(main字段)
  • X/index.js
  • X/index.json
  • X/index.node

(3)如果 X 不带路径
  a. 根据 X 所在的父模块,确定 X 可能的安装目录。
  b. 依次在每个目录中,将 X 当成文件名或目录名加载。

(4) 抛出 "not found"

请看一个例子。

当前脚本文件 /home/ry/projects/foo.js 执行了 require('bar') ,这属于上面的第三种情况。Node 内部运行过程如下。

首先,确定 x 的绝对路径可能是下面这些位置,依次搜索每一个目录。

/home/ry/projects/node_modules/bar /home/ry/node_modules/bar /home/node_modules/bar /node_modules/bar

搜索时,Node 先将 bar 当成文件名,依次尝试加载下面这些文件,只要有一个成功就返回。

bar bar.js bar.json bar.node

如果都不成功,说明 bar 可能是目录名,于是依次尝试加载下面这些文件。

bar/package.json(main字段) bar/index.js bar/index.json bar/index.node

如果在所有目录中,都无法找到 bar 对应的文件或目录,就抛出一个错误。


node app.js
node process.js

线程

线程是操作系统能够进行运算调度最小单位,首先我们要清楚线程是隶属于进程的,被包含于进程之中。一个线程只能隶属于一个进程,但是一个进程是可以拥有多个线程的。

同一块代码,可以根据系统CPU核心数启动多个进程,每个进程都有属于自己的独立运行空间,进程之间是不相互影响的。同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage),线程又有单线程和多线程之分,具有代表性的 JavaScript、Java 语言。

单线程

单线程就是一个进程只开一个线程

Javascript 就是属于单线程,程序顺序执行,可以想象一下队列,前面一个执行完之后,后面才可以执行,当你在使用单线程语言编码时切勿有过多耗时的同步操作,否则线程会造成阻塞,导致后续响应无法处理。你如果采用 Javascript 进行编码时候,请尽可能的使用异步操作。

单线程使用总结

  • Node.js 虽然是单线程模型,但是其基于事件驱动、异步非阻塞模式,可以应用于高并发场景,避免了线程创建、线程之间上下文切换所产生的资源开销。
  • 如果你有需要大量计算,CPU 耗时的操作,开发时候要注意。

Node.js 是 Javascript 在服务端的运行环境,构建在 chrome 的 V8 引擎之上,基于事件驱动、非阻塞I/O模型,充分利用操作系统提供的异步 I/O 进行多任务的执行,适合于 I/O 密集型的应用场景,因为异步,程序无需阻塞等待结果返回,而是基于回调通知的机制,原本同步模式等待的时间,则可以用来处理其它任务,在 Web 服务器方面,著名的 Nginx 也是采用此模式(事件驱动),Nginx 采用 C 语言进行编写,主要用来做高性能的 Web 服务器,不适合做业务。Web业务开发中,如果你有高并发应用场景那么 Node.js 会是你不错的选择。

Node.js 中的进程 Process 是一个全局对象,无需 require 直接使用,给我们提供了当前进程中的相关信息。官方文档提供了详细的说明,感兴趣的可以亲自实践下 Process 文档。

  • process.env:环境变量,例如通过 process.env.NODE_ENV 获取不同环境项目配置信息
  • process.nextTick:这个在谈及 Event Loop 时经常为会提到
  • process.pid:获取当前进程id
  • process.ppid:当前进程对应的父进程
  • process.cwd():获取当前进程工作目录
  • process.platform:获取当前进程运行的操作系统平台
  • process.uptime():当前进程已运行时间,例如:pm2 守护进程的 uptime 值
  • 进程事件:process.on('uncaughtException', cb) 捕获异常信息、process.on('exit', cb)进程推出监听
  • 三个标准流:process.stdout 标准输出、process.stdin 标准输入、process.stderr 标准错误输出

关于 Node.js 进程的几点总结

  • Javascript 是单线程,但是做为宿主环境的 Node.js 并非是单线程的。
  • 由于单线程原故,一些复杂的、消耗 CPU 资源的任务建议不要交给 Node.js 来处理,当你的业务需要一些大量计算、视频编码解码等 CPU 密集型的任务,可以采用 C 语言。
  • Node.js 和 Nginx 均采用事件驱动方式,避免了多线程的线程创建、线程上下文切换的开销。如果你的业务大多是基于 I/O 操作,那么你可以选择 Node.js 来开发。

大多数同学对于 HTTP、HTTPS 会很熟悉,通常用于浏览器与服务端交互,或者服务端与服务端的交互,另外两个 Net 与 Dgram 也许会相对陌生,这两个是基于网络模型的传输层来实现的,分别对应于 TCP、UDP 协议,下面一图看明白 OSI 七层模型 与 TCP/IP 五层模型之间的关系,中间使用虚线标注了传输层,对于上层应用层(HTTP/HTTPS等)也都是基于这一层的 TCP 协议来实现的,所以想使用 Node.js 做服务端开发,Net 模块也是你必须要掌握的,这也是我们本篇要讲解的重点。

TCP 是传输控制协议,大多数情况下我们都会使用这个协议,因为它是一个更可靠的数据传输协议,具有如下三个特点:

  • 面向链接: 需要对方主机在线,并建立链接。
  • 面向字节流: 你给我一堆字节流的数据,我给你发送出去,但是每次发送多少是我说了算,每次选出一段字节发送的时候,都会带上一个序号,这个序号就是发送的这段字节中编号最小的字节的编号。
  • 可靠: 保证数据有序的到达对方主机,每发送一个数据就会期待收到对方的回复,如果在指定时间内收到了对方的回复,就确认为数据到达,如果超过一定时间没收到对方回复,就认为对方没收到,在重新发送一遍。

三次握手

上面三个特点说到 TCP 是面向链接和可靠的,其一个显著特征是在传输之前会有一个 3 次握手,实现过程如下所示:

 

在一次 TCP 三次握手的过程中,客户端与服务端会分别提供一个套接字来形成一个链接。之后客户端与服务端通过这个链接来互相发送数据。

先清楚一个概念http请求与tcp链接之间的关系,在客户端向服务端请求和返回的过程中,是需要去创建一个TCP connection,因为http是不存在链接这样一个概念的,它只有请求和响应这样一个概念,请求和响应都是一个数据包,中间要通过一个传输通道,这个传输通道就是在TCP里面创建了一个从客户端发起和服务端接收的一个链接,TCP链接在创建的时候是有一个三次握手(三次网络传输)这样一个消耗在的。

 

第一次握手: 建立连接,客户端A发送SYN=1、随机产生Seq=client_isn的数据包到服务器B,等待服务器确认。

第二次握手: 服务器B收到请求后确认联机(可以接受数据),发起第二次握手请求,ACK=(A的Seq+1)、SYN=1,随机产生Seq=client_isn的数据包到A。

第三次握手: A收到后检查ACK是否正确,若正确,A会在发送确认包ACK=服务器B的Seq+1、ACK=1,服务器B收到后确认Seq值与ACK值,若正确,则建立连接。

TCP标示:

  1. SYN(synchronous建立联机)
  2. ACK(acknowledgement 确认)
  3. Sequence number(顺序号码)

总结: 

至于为什么要经过三次握手呢,是为了防止服务端开启一些无用的链接,保证双方的有效率传输。网络传输是有延时的,中间可能隔着非常远的距离,通过光纤或者中间代理服务器等,客户端发送一个请求,服务端收到之后如果直接创建一个链接,返回内容给到客户端,因为网络传输原因,这个数据包丢失了,客户端就一直接收不到服务器返回的这个数据,超过了客户端设置的时间就关闭了,那么这时候服务端是不知道的,它的端口就会开着等待客户端发送实际的请求数据,服务这个开销也就浪费掉了。只有经过三次握手,才能确定双方的收、发功能都是正常的,那么彼此之间的通讯也就得到保障了,也就不存在上面的开销浪费了。


I/O 是 Input/Ouput 的缩写,即输入输出端口,是信息处理系统(例如计算机)与外部世界(可能是人类或另一信息处理系统)之间的通信。输入是系统接收的信号或数据,输出则是从其发送的信号或数据。

I/O 也是一个很宽泛的词,每个设备都会有一个专用的 I/O 地址,用来处理自己的输入输出信息。对于服务端研发的童鞋相信 网络 I/O磁盘 I/O 这些词,也需并不陌生,一次 API 接口调用、向磁盘写入日志信息,其实就是在跟 I/O 打交道。一次 I/O 操作分为等待资源使用资源两个阶段,以下分别进行介绍。

阻塞与非阻塞 I/O 是对于操作系统内核而言的,发生在等待资源阶段,根据发起 I/O 请求是否阻塞来判断。

阻塞 I/O:这种模式下一个用户进程在发起一个 I/O 操作之后,只有收到响应或者超时才可进行处理其它事情,否则 I/O 将会一直阻塞。以读取磁盘上的一段文件为例,系统内核在完成磁盘寻道、读取数据、复制数据到内存中之后,这个调用才算完成。阻塞的这段时间对 CPU 资源是浪费的。 非阻塞 I/O:这种模式下一个用户进程发起一个 I/O 操作之后,如果数据没有就绪,会立刻返回(标志数据资源不可用),此时 CPU 时间片可以用来做一些其它事情。

同步与异步 I/O 发生在使用资源阶段,根据实际 I/O 操作来判断。

同步 I/O:应用发送或接收数据后,如果不返回,继续等待(此处发生阻塞),直到数据成功或失败返回。 异步 I/O:应用发送或接收数据后立刻返回,数据写入 OS 缓存,由 OS 完成数据发送或接收,并返回成功或失败的信息给应用。Node.js 就是典型的异步编程例子。

OSI 七层模型与网际网协议族图

可以看到这里以传输层做了边界划分,传输层之上为用户空间(Web 客户端、浏览器、FTP 这些都属于上三层),下四层为内核空间,例如传输层的 TCP、UDP 协议就对应到了内核空间。


Git

Git 当下最流行的版本管理工具

git initgit add -A .git add -Agit add .git add -ugit commit -m '版本信息'git statusgit push -u origin mastergit pullgit branch -avgit branch -vvgit reset --hard a3f40baadd5fea57b1b40f23f9a54a644eebd52e
git branch -agit branch devgit branchgit checkout devgit branch -d devgit push origin :dev
  • 方法1,先删后加:
git remote rm origingit remote add origin 仓库地址
  • 方法2,修改命令:
git remote set-url origin 仓库地址
git pull
git fetch origin mastergit log -p master..origin/mastergit merge origin/master
git remote add origin git@github.com:XXXX/nothing2.gitgit checkout -b dev origin/dev
git branch -agit fetch origin devgit checkout -b dev origin/devgit pull origin dev

SEO优化

SEO(Search Engine Optimization):汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。

优化策略

1.主题要明确,内容要丰富

在设计制作网站之前,要清晰设定网络的主题、用途和内容,网站主题须明确突出,内容丰富饱满,以符合用户体验为原则。对于一个网站来说,优化网站的主题与实际内容才是最为重要的。一个网站需要有鲜明的主题,丰富的与主题相关的内容,专注于某些领域的变化的,及时更新。

2.引出链接要人气化

搜索引擎判断网站的好坏的一个标准是外部链接的多少以及所链接的网站质量。创建有人气化的、有意义的引出链接,提高链接广泛度,既能提高在搜索引擎的排名,同时也可以起到互相宣传的作用。

3.关键词设定要突出

网站的关键词非常重要,它决定网站是否能被用户搜索到,因此在关键词的选择上要特意注意。关键词的选择必须突出,遵循一定的原则,如:关键词要与网站主题相关,不要一味的追求热门词汇;避免使用含义很广的一般性词汇;根据产品的种类及特性,尽可能选取具体的词;选取人们在使用搜索引擎时常用到与网站所需推广的产品及服务相关的词。5至10个关键词数量是比较适中的,密度可为2%—8%。要重视在标题(Page Title)、段落标题(Heading)这两个网页中最重要最显眼的位置体现关键词,还须在网页内容、图片的alt属性、META标签等网页描述上均可不同的程度设置突出关键词。

4.网站架构层次要清晰

网站结构上尽量避免采用框架结构,导航条尽量不使用FLASH按钮。首先要重视网站首页的设计,因为网站的首页被搜索引擎检测到的概率要比其他网页大得多。通常要将网站的首页文件放在网站的根目录下,因为根目录下的检索速度最快。其次要注意网站的层次(即子目录)不宜太多,一级目录不超过两个层次,详细目录也不要超过四个层次。最后,网站的导航尽量使用纯文字进行导航,因为文本要比图片表达的信息更多。

5.页面容量要合理化

网页分为静态网页与动态网页两种,动态网页即具有交互功能的网页,也就是通过数据库搜索返回数据,这样搜索引擎在搜索时所费的时间较长,而且一旦数据库中的内容更新,搜索引擎抓取的数据也不再准确,所以搜索引擎很少收录动态网页,排名结果也不好。而静态网页不具备交互功能,即单纯的信息介绍,搜索引擎搜索时所费时间短,而且准确,所以愿意收录,排名结果比较好。所以网站要尽量使用静态网页,减少使用动态网页。网页容量越小显示速度越快,对搜索引擎蜘蛛程序的友好度越高,因而在制作网页的时候要尽量精简HTML代码,通常网页容量不超过15kB。网页中的Java.script和CSS尽可能和网页分离。应该鼓励遵循W3C的规范使用,更规范的XHTML和XML作为显示格式。

6.网站导航要清晰化

搜素引擎是通过专有的蜘蛛程序来查找出每一个网页上的HTML代码,当网页上有链接时就逐个搜索,直到没有指向任何页面的链接。蜘蛛程序需要访问完所有的页面需要花费很长的时间,所以网站的导航需要便于蜘蛛程序进行索引收录。可根据自己的网站结构,制作网站地图simemap.html,在网页地图中列出网站所有子栏目的链接,并将网站中所有的文件放在网站的根目录下。网站地图可增加搜索引擎友好度,可让蜘蛛程序快速访问整个站点上的所有网页和栏目。

7.网站发布要更新

为了更好的实现与搜索引擎对话,将经过优化的企业网站主动提交到各搜索引擎,让其免费收录,争取较好的自然排名。一个网站如果能够进行有规律的更新,那么搜索引擎更容易收录。因而合理的更新网站也是搜索引擎优化的一个重要方法。 [1] 

SEO实战

TDK优化

titledescriptionkeywordstitlekeywordsdescription

页面内容优化

使用html5结构

html5.jsheaderfootersectionasidenavarticle

更多html5语义化标签请参考:All HTML5 Tags

唯一的H1标题

headerfootersectionasidearticle

首页的h1标题为站点名称,内页的h1标题为各个内页的标题,如分类页用分类的名字,详细页用详细页标题作为h1标题

alt
imgalt

nofollow

nofollow

正文

内容方面考虑:

  • 自然写作
  • 高质量原创内容
  • 吸引阅读的写作手法
  • 突出卖点
  • 增强信任感
  • 引导进一步行为

用户体验方面考虑:

  • 排版合理、清晰、美观、字体、背景易于阅读
  • 实质内容处在页面最重要位置,用户一眼就能看到
  • 实质内容与广告能够清晰区分
  • 第一屏就有实质内容,而不是需要下拉页面才能看到
  • 广告数量不宜过多,位置不应该妨碍用户阅读
  • 如果图片、视频有利于用户理解页面内容,尽量制作图片、视频等
  • 避免过多弹窗

URL优化

URL设计原则:

-_

URL静态化

以现在搜索引擎的爬行能力是可以不用做静态化的,但是从收录难易度,用户体验及社会化分享,静态简短的URL都是更有利的。

URL规范化

1、统一连接

以上四个其实都是首页,虽然不会给访客造成什么麻烦,但对于搜索引擎来说就是四条网址,并且内容相同,很可能会被误认为是作弊手段,而且当搜索引擎要规范化网址时,需要从这些选择当中挑一个最好的代表,但是挑的这个不一定是你想要的。所以最好自己就规范好。

2、301跳转

第一种是URL发生改变,一定要把旧的地址301指向新的,不然之前做的一些收录权重什么的全白搭了。

node/nid

3、canonical

这个标签表示页面的唯一性(这个标签以前百度不支持,现在支持),用在平时参数传递的时候,如:

headcanonical

robots

robots.txt

搜索引擎蜘蛛访问网站时会第一个访问robots.txt文件,robots.txt用于指导搜索引擎蜘蛛禁止抓取网站某些内容或只允许抓取那些内容,放在站点根目录。

以腾讯课堂的robots.txt为例:

*#

下面表示禁止所有搜索引擎蜘蛛抓取任何内容

下面表示允许所有搜索引擎蜘蛛抓取任何内容

注意:被robots禁止抓取的URL还是可能被索引并出现在搜索结果中的。只要有导入链接指向这个URL,搜索引擎就知道这个URL的存在,虽然不会抓取页面内容,但是索引库还是有这个URL的信息。以淘宝为例:

禁止百度搜索引擎抓取

百度搜索有显示

robots.txt

meta robots

如果要想URL完全不出现在搜索结果中,则需设置meta robots

上面代码表示:禁止所有搜索引擎索引本页,禁止跟踪本页上的链接。

当然还有其他类型的content,不过各个浏览器支持情况不同,所以这里忽略。

sitemap

站点地图格式分为HTML和XML两种。

sitemap.html
utf-8
urlseturlloclastmodchangefreqpriority
lastmod
changefreq
priority0.0-1.01.00.00.5
sitemap.xml

SEO工具

  • 百度搜索风云榜
  • 百度指数
  • 百度站长平台
  • meta seo inspector,检查标签的,谷歌插件
  • seo in china,百度收录的各种数据,谷歌插件
  • check my links,检查链接,谷歌插件
  • seo quake,统计各种数据,谷歌插件

最后,本文参考百度搜索引擎优化指南2.0 和zac著作《SEO实战密码》(对SEO感兴趣的同学,可以买本看看)。


let、const、class和var的区别

顶层对象(浏览器环境指 window、Node.js 环境指 Global)的属性和全局变量属性的赋值是相等价的

  • 使用 var 和 function 声明的是顶层对象的属性,而 let 就属于 ES6 规范了,但是 ES6 规范中 let、const、class 这些声明的全局变量,不再属于顶层对象的属性。
  • let声明的变量是块级作用域(所在花括号里),var是函数作用域和全局作用域
  • 从代码的写法上,let不能声明同名的变量,var可以。
  • var声明变量存在变量提升,let和const不存在变量提升

LOGO语言中的两个图形连在一起用什么函数 logo语言的两种工作方式

js三大事件(鼠标事件、键盘事件、html事件)

鼠标事件

  • click:单击
  • dblclick:双击
  • mousedown:鼠标按下
  • mouseup:鼠标抬起
  • mouseover:鼠标悬浮
  • mouseout:鼠标离开
  • mousemove:鼠标移动
  • mouseenter:鼠标进入
  • mouseleave:鼠标离开

键盘事件

  • keydown:按键按下
  • keyup:按键抬起
  • keypress:按键按下抬起

HTML事件

  • load:文档加载完成
  • select:被选中的时候
  • change:内容被改变
  • focus:得到光标
  • resize:窗口尺寸变化
  • scroll:滚动条移动

首先,请牢记2点:

(1) JS是单线程语言

(2) JS的Event Loop是JS的执行机制。深入了解JS的执行,就等于深入了解JS里的event loop

例1,观察它的执行顺序

运行结果是: 1 3 2

也就是说,setTimeout里的函数并没有立即执行,而是延迟了一段时间,满足一定条件后,才去执行的,这类代码,我们叫异步代码。

所以,这里我们首先知道了JS里的一种分类方式,就是将任务分为: 同步任务和异步任务

按照这种分类方式:JS的执行机制是

  • 首先判断JS是同步还是异步,同步就进入主线程,异步就进入event table
  • 异步任务在event table中注册函数,当满足触发条件后,被推入event queue
  • 同步任务进入主线程后一直执行,直到主线程空闲时,才会去event queue中查看是否有可执行的异步任务,如果有就推入主线程中

以上三步循环执行,这就是event loop

所以上面的例子,你是否可以描述它的执行顺序了呢?

3.JS中的event loop(2)

所以,上面关于event loop就是我对JS执行机制的理解,直到我遇到了下面这段代码

例2:

尝试按照,上文我们刚学到的JS执行机制去分析

所以,结果是 【马上执行for循环啦 --- 代码执行结束 --- 定时器开始啦 --- 执行then函数啦】吗?

亲自执行后,结果居然不是这样,而是【马上执行for循环啦 --- 代码执行结束 --- 执行then函数啦 --- 定时器开始啦】

那么,难道是异步任务的执行顺序,不是前后顺序,而是另有规定? 事实上,按照异步和同步的划分方式,并不准确。

而准确的划分方式是:

  • macro-task(宏任务):包括整体代码script,setTimeout,setInterval
  • micro-task(微任务):Promise,process.nextTick

按照这种分类方式:JS的执行机制是

  • 执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的【事件队列】里
  • 当前宏任务执行完成后,会查看微任务的【事件队列】,并将里面全部的微任务依次执行完

重复以上2步骤,结合event loop(1) event loop(2) ,就是更为准确的JS执行机制了。

尝试按照刚学的执行机制,去分析例2:

所以最后的执行顺序是【马上执行for循环啦 --- 代码执行结束 --- 执行then函数啦 --- 定时器开始啦】

4. 谈谈setTimeout

这段setTimeout代码什么意思? 我们一般说: 3秒后,会执行setTimeout里的那个函数

但是这种说并不严谨,准确的解释是: 3秒后,setTimeout里的函数被会推入event queue,而event queue(事件队列)里的任务,只有在主线程空闲时才会执行。

所以只有满足 (1)3秒后 (2)主线程空闲,同时满足时,才会3秒后执行该函数

如果主线程执行内容很多,执行时间超过3秒,比如执行了10秒,那么这个函数只能10秒后执行了


webpack

什么是Webpack

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言或者高级语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。

为什要使用WebPack

今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,前端社区涌现出了很多好的实践方法

a:模块化,让我们可以把复杂的程序细化为小的文件;

b:类似于TypeScript这种在JavaScript基础上拓展的开发语言:使我们能够实现目前版本的JavaScript不能直接使用的特性,并且之后还能能装换为JavaScript文件使浏览器可以识别;

c:scss,less等CSS预处理器

.........

这些改进确实大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理又是非常繁琐的,这就为WebPack类的工具的出现提供了需求

Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。


DOCTYPE

DOCTYPE全称Document Type Declaration(文档类型声明,缩写DTD)

DTD的声明影响浏览器对于CSS代码及Javascript脚本的解析。

<!DOCTYPE>声明叫做文件类型定义(DTD),声明的作用为了告诉浏览器该文件的类型。让浏览器解析器知道应该用哪个规范来解析文档。<!DOCTYPE>声明必须在 HTML 文档的第一行,这并不是一个 HTML 标签。

严格模式与混杂模式如何区分?它们有何意义?

严格模式:又称标准模式,是指浏览器按照 W3C 标准解析代码。
混杂模式:又称怪异模式或兼容模式,是指浏览器用自己的方式解析代码。

如何区分:浏览器解析时到底使用严格模式还是混杂模式,与网页中的 DTD 直接相关。
1、如果文档包含严格的 DOCTYPE ,那么它一般以严格模式呈现。(严格 DTD ——严格模式) 
2、包含过渡 DTD 和 URI 的 DOCTYPE ,也以严格模式呈现,但有过渡 DTD 而没有 URI (统一资源标识符,就是声明最后的地址)会导致页面以混杂模式呈现。(有 URI 的过渡 DTD ——严格模式;没有 URI 的过渡 DTD ——混杂模式) 
3、DOCTYPE 不存在或形式不正确会导致文档以混杂模式呈现。(DTD不存在或者格式不正确——混杂模式)
4、HTML5 没有 DTD ,因此也就没有严格模式与混杂模式的区别,HTML5 有相对宽松的语法,实现时,已经尽可能大的实现了向后兼容。( HTML5 没有严格和混杂之分)

意义:严格模式与混杂模式存在的意义与其来源密切相关,如果说只存在严格模式,那么许多旧网站必然受到影响,如果只存在混杂模式,那么会回到当时浏览器大战时的混乱,每个浏览器都有自己的解析模式。

用JS判断浏览器当前的模式:

  • document.compatMode=='CSS1Compat'?'标准模式':'混杂模式';
  • IE、Firefox、Opera、Sarari和Chrome都实现了这个属性;

IE8的特殊情况:

IE8又为document对象引入了一个名为documentMode新属性,这是因为IE8有3种不同的呈现模式,这个属性的值如果是5,则表示混杂模式(即IE5模式);如果是7,则表示IE7仿真模式;如果是8,则表示IE8标准模式。


get和post的区别

  • 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。
  • get只能传输少量数据(url长度限制),而post可传输的数据容量会更大
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

但是,最底层的区别是:GET产生一个TCP数据包;POST产生两个TCP数据包。

GET和POST是什么?HTTP协议中的两种发送请求的方法。

HTTP是什么?HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议。

HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。GET和POST能做的事情是一样一样的。你要给GET加上request body,给POST带上url参数,技术上是完全行的通的。 

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据)

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

也就是说,GET只需要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。

因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?

1. GET与POST都有自己的语义,不能随便混用。

2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。

3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。


h5新特性

语义化标签

用最恰当的HTML元素标记的内容。

优点

  1. 提升可访问性
  2. SEO
  3. 结构清晰,利于维护

通用容器:

  1. div 块级通用容器
  2. span 短语内容无语义容器

标签新属性

细说data-* dataset(IE11,火狐谷歌)

在HTML5中我们可以使用data-前缀设置我们需要的自定义属性,来进行一些数据的存放。通过dataset来获取这些数据。这里的data-前缀就被称为data属性,其可以通过脚本进行定义,也可以应用CSS属性选择器进行样式设置。数量不受限制,在控制和渲染数据的时候提供了非常强大的控制。

一个实例教你如何使用data dataset

classList(火狐谷歌最新,IE10以上)

  • obj.classList.add() 添加class类
  • obj.classList.remove() 移出class类
  • obj.classList.contains() 判断是否包含指定class类
  • obj.classList.toggle() 切换class类
  • obj.classList.length 获取class类的个数

HTML5新表单

新的input类型

email

url

number

range

search

新的form属性

autocomplete

novalidate

新的input属性

autocomplete

autofocus

form

form overrides (formaction, formenctype, formmethod, formnovalidate, formtarget)

height 和 width 属性

list 属性

min、max 和 step 属性

multiple 属性

novalidate 属性

pattern 属性

placeholder 属性

required 属性

音频(audio)和视频(video)

支持的格式和写法

音频元素支持的3种格式:Ogg MP3 Wav

视频元素支持三种视频格式:MP4、WebM、Ogg。

标签属性

  • 音视频:autoplay、controls、loop、muted、preload、src
  • 视频:autoplay、controls、loop、muted、width、height、poster、preload、src

方法

  • load():重新加载音频/视频元素
  • play():开始播放音频/视频
  • pause():暂停当前播放的音频/视频

事件

  • durationchange:当音频/视频的时长已更改时
  • ended:当目前的播放列表已结束时
  • pause:当音频/视频已暂停时
  • play:当音频/视频已开始或不再暂停时
  • ratechange:当音频/视频的播放速度已更改时
  • timeupdate:当目前的播放位置已更改时
  • volumechange:当音量已更改时

事件属性

  • 只读属性
  • duration:返回当前的总时长
  • currentSrc:返回当前URL
  • ended:返回是否已结束
  • paused:返回是否已暂停
  • 获取并可修改的属性:
  • autoplay:设置或返回是否自动播放
  • controls:设置或返回是否显示控件(比如播放/暂停等)
  • loop:设置或返回是否是循环播放
  • muted:设置或返回是否静音
  • currentTime:设置或返回当前播放位置(以秒计)
  • volume:设置或返回音量(规定音频/视频的当前音量。必须是介于 0.0 与 1.0 之间的数字。)
    1.0 是最高音量(默认);0.5 是一半音量 (50%); 0.0 是静音;
  • playbackRate:设置或返回播放速度

css3新特性

过渡

动画

形状转换

选择器

阴影

边框

边框图片

边框圆角

background-size

文字

换行

word-break: normal|break-all|keep-all;
word-wrap: normal|break-word;
text-overflowtext-overflowclip|ellipsis|stringclipstring

超出省略号

多行超出省略号

超出省略号。这个对于大家来说,不难!但是以前如果是多行超出省略号,就只能用js模拟!现在css3提供了多行省略号的方法!遗憾就是这个暂时只支持webkit浏览器!

颜色

rgba

一个是rgba(rgb为颜色值,a为透明度)

hsla

h:色相”,“s:饱和度”,“l:亮度”,“a:透明度”

渐变

弹性布局——flex

盒模型定义

box-sizing这个属性,网上说法是:属性允许您以特定的方式定义匹配某个区域的特定元素。

  • box-sizing:border-box的时候,边框和padding包含在元素的宽高之内!
  • box-sizing:content-box的时候,边框和padding不包含在元素的宽高之内!

媒体查询

rem布局——rem是根em(root em)的缩写。rem是和根元素关联的,不依赖当前元素。不管你在文档中的什么地方使用这个单位,1.2rem的计算值是相等的,等于1.2倍的根元素的字号大小。


 伪类与伪元素

css 引入伪类和伪元素概念是为了格式化文档树以外的信息。也就是说,伪类和伪元素是用来修饰不在文档树中的部分

对伪类和伪元素进行解释:

伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。比如说,当用户悬停在指定的元素时,我们可以通过:hover 来描述这个元素的状态。虽然它和普通的 css 类相似,可以为已有的元素添加样式,但是它只有处于 dom 树无法描述的状态下才能为元素添加样式,所以将其称为伪类。

伪元素用于创建一些不在文档树中的元素,并为其添加样式。比如说,我们可以通过:before 来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。

伪类与伪元素的区别

伪类:

伪类的操作对象是文档树中已有的元素,而伪元素则创建了一个文档数外的元素。因此,伪类与伪元素的区别在于:有没有创建一个文档树之外的元素。

 伪元素是使用单冒号还是双冒号?

CSS3 规范中的要求使用双冒号 (::) 表示伪元素,以此来区分伪元素和伪类,比如::before 和::after 等伪元素使用双冒号 (::),:hover 和:active 等伪类使用单冒号 (:)。除了一些低于 IE8 版本的浏览器外,大部分浏览器都支持伪元素的双冒号 (::) 表示方法。


mongodb

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

为什么要用MongoDB

(1)MongoDB提出的是文档、集合(多条记录)的概念,使用BSON(类JSON)作为其数据模型结构,其结构是面向对象的而不是二维表,存储一个用户在MongoDB中是这样子的。

使用这样的数据模型,使得MongoDB能在生产环境中提供高读写的能力,吞吐量较于mysql等SQL数据库大大增强。

(2)易伸缩,自动故障转移。易伸缩指的是提供了分片能力,能对数据集进行分片,数据的存储压力分摊给多台服务器。自动故障转移是副本集的概念,MongoDB能检测主节点是否存活,当失活时能自动提升从节点为主节点,达到故障转移。

(3)数据模型因为是面向对象的,所以可以表示丰富的、有层级的数据结构,比如博客系统中能把“评论”直接怼到“文章“的文档中,而不必像myqsl一样创建三张表来描述这样的关系

几个shell实操

因为本篇文章不是API手册,所有这里对shell的使用也是基础的介绍什么功能可以用什么语句,主要是为了展示使用MongoDB shell的方便性,如果需要知道具体的MongoDB shell语法可以查阅官方文档。

1、切换数据库

创建数据库并不是必须的操作,数据库与集合只有在第一次插入文档时才会被创建,与对数据的动态处理方式是一致的。简化并加速开发过程,而且有利于动态分配命名空间。如果担心数据库或集合被意外创建,可以开启严格模式

2、插入语法

3、查找语法

4、更新语法

5、删除语法

6、索引相关语法

7、基本管理语法

Mongobd的重要模块–GridFS

GridFS是Mongo的一个子模块,使用GridFS可以基于MongoDB来持久存储文件。并且支持分布式应用(文件分布存储和读取)。作为MongoDB中二进制数据存储在数据库中的解决方案,通常用来处理大文件,对于MongoDB的BSON格式的数据(文档)存储有尺寸限制,最大为16M。但是在实际系统开发中,上传的图片或者文件可能尺寸会很大,此时我们可以借用GridFS来辅助管理这些文件。

GridFS存储原理

GridFS使用两个集合(collection)存储文件。一个集合是chunks, 用于存储文件内容的二进制数据;一个集合是files,用于存储文件的元数据。

GridFS会将两个集合放在一个普通的buket中,并且这两个集合使用buket的名字作为前缀。MongoDB的GridFs默认使用fs命名的buket存放两个文件集合。因此存储文件的两个集合分别会命名为集合fs.files ,集合fs.chunks。

当把一个文件存储到GridFS时,如果文件大于chunksize (每个chunk块大小为256KB),会先将文件按照chunk的大小分割成多个chunk块,最终将chunk块的信息存储在fs.chunks集合的多个文档中。然后将文件信息存储在fs.files集合的唯一一份文档中。其中fs.chunks集合中多个文档中的file_id字段对应fs.files集中文档”_id”字段。

读文件时,先根据查询条件在files集合中找到对应的文档,同时得到“_id”字段,再根据“_id”在chunks集合中查询所有“files_id”等于“_id”的文档。最后根据“n”字段顺序读取chunk的“data”字段数据,还原文件。

mongoose是nodeJS提供连接 mongodb的一个库,类似于jquery和js的关系,对mongodb一些原生方法进行了封装以及优化。简单的说,Mongoose就是对node环境中MongoDB数据库操作的封装,一个对象模型工具,将数据库中的数据转换为JavaScript对象以供我们在应用中使用。


小程序

小程序提供了一个简单、高效的应用开发框架和丰富的组件及API,帮助开发者在微信中开发具有原生 APP 体验的服务。

WXMLWXSSJavaScript

响应的数据绑定

框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。(声明式渲染{{}})

页面管理

框架 管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到 框架 中,其他的一切复杂的操作都交由 框架 处理。

基础组件

框架 提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,创建出强大的微信小程序 。

丰富的 API

框架 提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。

云开发

开发者可以使用云开发开发微信小程序、小游戏,无需搭建服务器,即可使用云端能力。

云开发为开发者提供完整的原生云端支持和微信服务支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代,同时这一能力,同开发者已经使用的云服务相互兼容,并不互斥。

云开发提供了几大基础能力支持:

能力

作用

说明

云函数

无需自建服务器

在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码

数据库

无需自建数据库

一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库

存储

无需自建存储和 CDN

在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理

云调用

原生微信服务集成

基于云函数免鉴权使用小程序开放接口的能力,包括服务端调用、获取开放数据等能力


js 深拷贝 vs 浅拷贝

堆和栈的区别

其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。

堆和栈都是内存中划分出来用来存储的区域。

栈(stack)为自动分配的内存空间,它由系统自动释放;而堆(heap)则是动态分配的内存,大小不定也不会自动释放。

对象

数组

深拷贝:

思路就是递归调用刚刚的浅拷贝,把所有属于对象的属性类型都遍历赋给另一个对象即可。我们直接来看一下 Zepto 中深拷贝的代码:

$.extend
$.extend

浏览器的兼容性

所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况。

  • 渐进增强(progressive enhancement): 针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验
  • 优雅降级`(graceful degradation): 一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

 Web标准是由万维网联盟(W3C)制订的,WEB标准的产生,网页内容能被更多的用户所访问到,文件下载和页面显示速度更快,所有页面都能提供适合打印的版本,网页开发人员开发更快捷,代码更易于维护,提高了搜索引擎的精确性,提高了网站的易用性

  我们需要注意的代码标准有:

主流浏览器的内核

    浏览器内核主要指的是浏览器的渲染引擎,渲染引擎决定了浏览器如何加载和显示网页的内容以及信息。我们主要用于测试的浏览器都有:IE、Chrome、Firefox、Safari、Opera、360浏览器。

  • IE:trident内核(IE内核)
  • Firefox:geoko内核,Mozilla自己开发的一套开放源代码、以C++编写的渲染引擎。
  • Safari:webkit内核,开源的浏览器引擎,源自于Linux平台上的一个引擎,经过Apple公司的修改可以支持Mac与Windows平台。
  • Chrome:Blink内核,Google和Opera Software共同研发。
  • Opera:以前是presto内核,现在改为Blink内核。
  • 360浏览器: 兼容模式(trident内核)、极速模式(Blink内核)。

 标准模式(Standards Mode)和怪异模式 (Quirks Mode)

    在Netscape Navigator和Microsoft Internet Explorer为数不多的浏览器盛行时,他们对网页有不同的实现方式,那个时候的网页都是针对这两个浏览器写的。随着各种浏览器的兴起,加上Web标准的制定,现在的浏览器不能继续使用以前的页面了,所以浏览器引入了标准模式和怪异模式来解决这一问题。

    标准模式就是浏览器按照Web标准来渲染页面;为了解决浏览器还是能使用以前写的页面,所以怪异模式就产生了。怪异模式在不同的浏览器显示都是不一样的,因为他们都是按照自己的方式来渲染页面。

    我们知道了标准模式和怪异模式,可是浏览器是怎么选择模式来渲染页面的呢?我们经常在页面的开头看到<!DOCTYPE>声明,这是告诉浏览器选择哪个版本的HTML,对于渲染模式的选择,浏览器是根据DTD的声明。如果网页中有DTD标准文档的声明,那浏览器会按照标准模式来渲染网页;如果网页没有DTD声明或者HTML4以下的DTD声明,那浏览器就按照自己的方式渲染页面,页面进入怪异模式。

CSS盒模型

    如果想要了解详细解说,请移至:

    盒模型指定元素如何显示,理解它,对我们的布局有很大的帮助。盒模型由内容(content)、内边距(padding)、边框(border)、外边距(margin)组成。

    盒模型有两种:IE盒模型(图1)、标准的W3C盒模型(图2)。从图1和图2就可以看出,IE盒模型的width包括了border、padding、content,而W3C盒模型的width仅限于content。

    在CSS3的属性中,box-sizing可以设置盒模型类型,默认值为content-boxcontent-box表示W3C盒模型,border-box表示IE盒模型。

                               图1. IE盒模型                                                                         图2. W3C盒模型

重置浏览器样式

    不同的浏览器对标签的默认样式值不同,所以我们需要有一套样式表来重置浏览器样式,避免我们写的网页在各个浏览器中造成的显示差异。

可以使用Normalize.css只是一个很小的css文件,但它在默认的HTML元素样式上提供了跨浏览器的高度一致性。相比于传统的css reset,Normalize.css是一种现代的,为HTML5准备的优质替代方案。

Normalize.css只是一个很小的css文件,但它在默认的HTML元素样式上提供了跨浏览器的高度一致性。相比于传统的css reset,Normalize.css是一种现代的,为HTML5准备的优质替代方案。

表现与数据分离

也可以说是界面与数据分离,要体现在代码上,操作数据的代码和操作界面的代码,要分开写。

优势:当页面需求发生改变,只需要改写界面的代码,并且修改的代码不能影响到操作数据访问的代码。

如MVVM框架,就是视图与数据分离,具体为:数据模型以及业务逻辑为model,保存具体数据以及操作数据行为(增删改查更新等)的方法。操作DOM视图的方法分为view

HTML语义化

    HTML语义化就是页面去掉样式或者加载失败的时候能够让页面呈现出清晰的结构。HTML5新增了好多标签,例如:header、footer、nav、menu、section、article等等,我们单单从字面上理解,就知道标签的含义。在写页面的时候,我们可以直接引用这些标签,不需要再用没有任何含义的div标签了,对于机器可以识别,对于开发人员,很容易明白,这就是HTML语义化。

    HTML语义化的好处有:有利于SEO优化,利于被搜索引擎收录,更便于搜索引擎的爬虫程序来识别;便于项目的开发及维护,使HTML代码更具有可读性,便于其他设备解析。

CSS选择器优先级

    掌握选择器优先级,再也不用!important来到处打补丁。

    CSS的基本选择器:

  • id选择器(用DOM的id申明)
  • 类选择器(用一个样式类名申明)和伪类
  • 属性选择器(用DOM的属性申明)
  • 标签选择器(用HTML标签申明)和伪元素

    还有一种添加样式可以在标签上直接添加,属于行内样式。

    在这里,我们只做简单说明,以上面几种选择器来排序:行内元素 < id选择器 < 类选择器/属性选择器 < 标签选择器。

:not()

清除浮动

    如果容器中有浮动的元素,容器的高度不能自动延长适应内容的高度,使得内容溢出到容器外而影响页面布局,为了避免这种情况的发生,我们需要用CSS来清除元素的浮动。

    一般常用的方法有三种:

    A. 在浮动元素后面添加带有clear属性的空元素

    B. 给容器添加属性overflow: hidden或者overflow: auto,在IE6中还需触发haslayout,所以还需添加zoom: 1。

    C. 使用:after伪元素


响应式布局等于流动网格布局,而自适应布局等于使用固定分割点来进行布局。

自适应布局给了你更多设计的空间,因为你只用考虑几种不同的状态。而在响应式布局中你却得考虑上百种不同的状态。虽然绝大部分状态差异较小,但仍然也算做差异。它使得把握设计最终效果变得更难,同样让响应式布局更加的难以测试和预测。

响应式布局概念

Responsive design,意在实现不同屏幕分辨率的终端上浏览网页的不同展示方式。通过响应式设计能使网站在手机和平板电脑上有更好的浏览阅读体验。

响应式设计的步骤

1. 设置 Meta 标签

[1](user-scalable = no 属性能够解决 iPad 切换横屏之后触摸才能回到具体尺寸的问题。 )

3. 通过媒介查询来设置样式 Media Queries

Media Queries 是响应式设计的核心。·

它根据条件告诉浏览器如何为指定视图宽度渲染页面。假如一个终端的分辨率小于 980px,那么可以这样写:

这里的样式就会覆盖上面已经定义好的样式。

4. 设置多种试图宽度

假如我们要设定兼容 iPad 和 iphone 的视图,那么可以这样设置:·

一些注意的

1. 宽度需要使用百分比

例如这样:

2. 处理图片缩放的方法

  • 简单的解决方法可以使用百分比,但这样不友好,会放大或者缩小图片。那么可以尝试给图片指定的最大宽度为百分比。假如图片超过了,就缩小。假如图片小了,就原尺寸输出。

CSS 控制:

3. 其他属性

preiframevideoimgtable

我们可以监测页面布局随着不同的浏览环境而产生的变化,如果它们变的过窄过短或是过宽过长,则通过一个子级样式表来继承主样式表的设定,并专门针对某些布局结构进行样式覆写。我们来看下代码示例:

下面的代码可以放在子级样式表Mobile.css中,专门针对移动设备进行样式覆写:

大致的视觉效果如下图所示:

横屏与竖屏的区别

 

图中上半部分是大屏幕设备所显示的完整页面,下面的则是该页面在小屏幕设备的呈现方式。页面HTML代码如下:

Media Queries

Ethan的文章中的“Meet the media query”部分有更多的范例及解释。更有效率的做法是,将多个media queries整合在一个样式表文件中

译文:流动网格


rem是什么?

rem(font size of the root element)是指相对于根元素的字体大小的单位。简单的说它就是一个相对单位。看到rem大家一定会想起em单位,em(font size of the element)是指相对于父元素的字体大小的单位。它们之间其实很相似,只不过一个计算的规则是依赖根元素一个是依赖父元素计算。·

为什么web app要使用rem?

这里我特别强调web app,web page就不能使用rem吗,其实也当然可以,不过出于兼容性的考虑在web app下使用更加能突显这个单位的价值和能力,接下来我们来看看目前一些企业的web app是怎么做屏幕适配的。·

1、实现强大的屏幕适配布局:

最近iphone6一下出了两款尺寸的手机,导致的移动端的屏幕种类更加的混乱,记得一两年前做web app有一种做法是以320宽度为标准去做适配,超过320的大小还是以320的规格去展示,这种实现方式以淘宝web app为代表作,但是近期手机淘宝首页进行了改版,采用了rem这个单位,首页以内依旧是和以前一样各种混乱,有定死宽度的页面,也有那种流式布局的页面。

我们现在在切页面布局的使用常用的单位是px,这是一个绝对单位,web app的屏幕适配有很多中做法,例如:流式布局、限死宽度,还有就是通过响应式来做,但是这些方案都不是最佳的解决方法。

例如流式布局的解决方案有不少弊端,它虽然可以让各种屏幕都适配,但是显示的效果极其的不好,因为只有几个尺寸的手机能够完美的显示出视觉设计师和交互最想要的效果,但是目前行业里用流式布局切web app的公司还是挺多的

上面的网站都是采用的流式布局的技术实现的,他们在页面布局的时候都是通过百分比来定义宽度,但是高度大都是用px来固定住,所以在大屏幕的手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度还是和原来一样,实际显示非常的不协调,这就是流式布局的最致命的缺点,往往只有几个尺寸的手机下看到的效果是令人满意的,其实很多视觉设计师应该无法接受这种效果,因为他们的设计图在大屏幕手机下看到的效果相当于是被横向拉长来一样。

流式布局并不是最理想的实现方式,通过大量的百分比布局,会经常出现许多兼容性的问题,还有就是对设计有很多的限制,因为他们在设计之初就需要考虑流式布局对元素造成的影响,只能设计横向拉伸的元素布局,设计的时候存在很多局限性。·

2.固定宽度做法

还有一种是固定页面宽度的做法,早期有些网站把页面设置成320的宽度,超出部分留白,这样做视觉,前端都挺开心,视觉在也不用被流式布局限制自己的设计灵感了,前端也不用在搞坑爹的流式布局。但是这种解决方案也是存在一些问题,例如在大屏幕手机下两边是留白的,还有一个就是大屏幕手机下看起来页面会特别小,操作的按钮也很小,手机淘宝首页起初是这么做的,但近期改版了,采用了rem。

3.响应式做法

响应式这种方式在国内很少有大型企业的复杂性的网站在移动端用这种方法去做,主要原因是工作大,维护性难,所以一般都是中小型的门户或者博客类站点会采用响应式的方法从web page到web app直接一步到位,因为这样反而可以节约成本,不用再专门为自己的网站做一个web app的版本。

4.设置viewport进行缩放

天猫的web app的首页就是采用这种方式去做的,以320宽度为基准,进行缩放,最大缩放为320*1.3 = 416,基本缩放到416都就可以兼容iphone6 plus的屏幕了,这个方法简单粗暴,又高效。说实话我觉得他和用接下去我们要讲的rem都非常高效,不过有部分同学使用过程中反应缩放会导致有些页面元素会糊的情况。

rem能等比例适配所有屏幕

上面讲了一大堆目前大部分公司主流的一些web app的适配解决方案,接下来讲下rem是如何工作的。

上面说过rem是通过根元素进行适配的,网页中的根元素指的是html我们通过设置html的字体大小就可以控制rem的大小。举个例子:

Demo 上面代码结果按钮大小如下图:

小button

 

我把html设置成10px是为了方便我们计算,为什么6rem等于60px。如果这个时候我们的.btn的样式不变,我们再改变html的font-size的值,看看按钮发生上面变化:

Demo

按钮大小结果如下:

2倍小button

 

上面的width,height变成了上面结果的两倍,我们只改变了html的font-size,但.btn样式的width,height的rem设置的属性不变的情况下就改变了按钮在web中的大小。

其实从上面两个案例中我们就可以计算出1px多少rem:

第一个例子:

120px = 6rem * 20px(根元素设置大值)

第二个例子:

240px = 6rem * 40px(根元素设置大值)

推算出:

10px  = 1rem 在根元素(font-size = 10px的时候);

20px  = 1rem 在根元素(font-size = 20px的时候);

40px  = 1rem 在根元素(font-size = 40px的时候);

在上面两个例子中我们发现第一个案例按钮是等比例放大到第二个按钮,html font-size的改变就会导致按钮的大小发生改变,我们并不需要改变先前给按钮设置的宽度和高度,其实这就是我们最想看到的,为什么这么说?接下来我们再来看一个例子:

 

由上面两个的demo中我们知道改变html的font-size可以等比改变所有用了rem单位的元素,所以大家可以通过chrome浏览器的调试工具去切换第三个的demo在不同设备下的展示效果,或者通过缩放浏览器的宽度来查看效果,我们可以看到不管在任何分辨率下,页面的排版都是按照等比例进行切换,并且布局没有乱。我只是通过一段js根据浏览器当前的分辨率改变font-size的值,就简单的实现了上面的效果,页面的所有元素都不需要进行任何改变。

到这里肯定有很多人会问我是怎么计算出不同分辨率下font-size的值?

首先假设我上面的页面设计稿给我时候是按照640的标准尺寸给我的前提下,(当然这个尺寸肯定不一定是640,可以是320,或者480,又或是375)来看一组表格。

上面的表格蓝色一列是Demo3中页面的尺寸,页面是以640的宽度去切的,怎么计算不同宽度下font-site的值,大家看表格上面的数值变化应该能明白。举个例子: = 0.6,384是640的0.6倍,所以384页面宽度下的font-size也等于它的0.6倍,这时384的font-size就等于12px。在不同设备的宽度计算方式以此类推。·

Demo3中我是通过JS去动态计算根元素的font-size,这样的好处是所有设备分辨率都能兼容适配,淘宝首页目前就是用的JS计算。但其实不用JS我们也可以做适配,一般我们在做web app都会先统计自己网站有哪些主流的屏幕设备,然后去针对那些设备去做media query设置也可以实现适配,例如下面这样:

上面的做的设置当然是不能所有设备全适配,但是用JS是可以实现全适配。具体用哪个就要根据自己的实际工作场景去定了。

下面推荐两个国内用了rem技术的移动站,大家可以上去参考看看他们的做法,手机淘宝目前只有首页用了rem,淘宝native app的首页是内嵌的web app首页。

淘宝首页:m.taobao.com

D X:m.dx.com

部分文章参考:web app变革之rem


响应式与自适应的区别

  • 1.自适应布局通过检测视口分辨率,来判断当前访问的设备是:pc端、平板、手机,从而请求服务层,返回不同的页面;响应式布局通过检测视口分辨率,针对不同客户端在客户端做代码处理,来展现不同的布局和内容。
  • 2.自适应布局需要开发多套界面,而响应式布局只需要开发一套界面就可以了。
  • 3.自适应对页面做的屏幕适配是在一定范围:比如pc端一般要大于1024像素,手机端要小于768像素。而响应式布局是一套页面全部适应。
  • 4.自适应布局如果屏幕太小会发生内容过于拥挤。而响应式布局正是为了解决这个问题而衍生出的概念,它可以自动识别屏幕宽度并做出相应调整的网页设计。

总之,响应式布局还是要比自适应布局要好一点,但是自适应布局更加贴切实际,因为你只需要考虑几种状态就可以了而不是像响应式布局需要考虑非常多状态。所以的说无论哪种设计都有它们各自的特点,我们要根据项目的需求来选择适合的布局方式。


 JavaScript 数据类型知识整理

先给出两道题目:

javascript中有哪些数据类型

JavaScript 中共有七种内置数据类型,包括基本类型对象类型

基本类型

基本类型分为以下六种:

  • string(字符串)
  • boolean(布尔值)
  • number(数字)
  • symbol(符号)
  • null(空值)
  • undefined(未定义)

注意

  1. string 、number 、boolean 和 null  undefined 这五种类型统称为原始类型(Primitive),表示不能再细分下去的基本类型
  2. symbol是ES6中新增的数据类型,symbol 表示独一无二的值,通过 Symbol 函数调用生成,由于生成的 symbol 值为原始类型,所以 Symbol 函数不能使用 new 调用;
  3. null 和 undefined 通常被认为是特殊值,这两种类型的值唯一,就是其本身。

对象类型

对象类型也叫引用类型,array和function是对象的子类型。对象在逻辑上是属性的无序集合,是存放各种值的容器。对象值存储的是引用地址,所以和基本类型值不可变的特性不同,对象值是可变的。

说说你对javascript是弱类型语言的理解?

JavaScript 是弱类型语言,而且JavaScript 声明变量的时候并没有预先确定的类型, 变量的类型就是其值的类型,也就是说变量当前的类型由其值所决定,夸张点说上一秒种的String,下一秒可能就是个Number类型了,这个过程可能就进行了某些操作发生了强制类型转换。虽然弱类型的这种不需要预先确定类型的特性给我们带来了便利,同时也会给我们带来困扰。为了能充分利用该特性就必须掌握类型转换的原理

javascript中强制类型转换是一个非常易出现bug的点,知道强制转换时候的规则吗?

ToPrimitive(转换为原始值)

ToPrimitive对原始类型不发生转换处理,只针对引用类型(object)的,其目的是将引用类型(object)转换为非对象类型,也就是原始类型。

ToPrimitive 运算符接受一个值,和一个可选的 期望类型作参数。ToPrimitive 运算符将值转换为非对象类型,如果对象有能力被转换为不止一种原语类型,可以使用可选的 期望类型 来暗示那个类型。

转换后的结果原始类型是由期望类型决定的,期望类型其实就是我们传递的type。直接看下面比较清楚。 ToPrimitive方法大概长这么个样子具体如下。

type不同值的说明

  • type为string:
  1. 先调用obj的toString方法,如果为原始值,则return,否则第2步
  2. 调用obj的valueOf方法,如果为原始值,则return,否则第3步
  3. 抛出TypeError 异常
  • type为number:
  1. 调用obj的valueOf方法,如果为原始值,则返回,否则下第2步
  2. 调用obj的toString方法,如果为原始值,则return,否则第3步
  3. 抛出TypeError 异常
  • type参数为空
  1. 该对象为Date,则type被设置为String
  2. 否则,type被设置为Number,即会首先检查该值是否有valueOf()方法,如果有并且返回基本类型值,就使用该值进行强制类型转换;如果没有就使用toString()的返回值(如果存在)来进行强制类型转换

Date数据类型特殊说明:

对于Date数据类型,我们更多期望获得的是其转为时间后的字符串,而非毫秒值(时间戳),如果为number,则会取到对应的毫秒值,显然字符串使用更多。 其他类型对象按照取值的类型操作即可。

ToPrimitive总结

ToPrimitive转成何种原始类型,取决于type,type参数可选,若指定,则按照指定类型转换,若不指定,默认根据实用情况分两种情况,Date为string,其余对象为number。那么什么时候会指定type类型呢,那就要看下面两种转换方式了。

toString

Object.prototype.toString()

toString() 方法返回一个表示该对象的字符串。参考:Object.prototype.toString()

每个对象都有一个 toString() 方法,当对象被表示为文本值时或者当以期望字符串的方式引用对象时,该方法被自动调用。对普通对象来说,除非自行定义,否则toString()返回内部属性[[Class]]的值,如"[object Object]"。

数组的默认toString()方法经过了重新定义,将所有单元字符串化以后再用","连接起来:

如果是原始类型,抽象操作ToString则负责处理非字符串到字符串的强制类型转换。

基本类型值的字符串化规则为:

null转换为"null",

undefined转换为"undefined",

true转换为""true"。

数字的字符串化遵循通用规则,那些极小和极大的数字使用指数形式:

valueOf

Object.prototype.valueOf()方法返回指定对象的原始值。

JavaScript 调用 valueOf() 方法用来把对象转换成原始类型的值(数值、字符串和布尔值)。但是我们很少需要自己调用此函数,valueOf 方法一般都会被 JavaScript 自动调用。

强制转换

NumberStringBoolean

Number()

Number

下面分成两种情况讨论,一种是参数是原始类型的值,另一种是参数是对象。

(1)原始类型值

原始类型值的转换规则如下。

NumberparseIntNaN
parseIntNumber
parseIntNumber

(2)对象

NumberNaN
Number
valueOfNumber
valueOftoStringtoStringNumber
toString

请看下面的例子。

Numberobjobj.valueOfobj.toString[object Object]NumberNaN
valueOftoStringtoString[object Object]
toString
valueOftoString
valueOftoString
NumbervalueOftoStringvalueOftoString

String()

String

(1)原始类型值

true"true"false"false""undefined""null"

(2)对象

String
StringNumbervalueOftoString
toStringStringtoStringvalueOfvalueOfStringvalueOf

下面是一个例子。

toString[object Object]valueOf
toStringvalueOf
toString
StringtoStringtoString[object Object]toStringvalueOf

Boolean()

Boolean
falsetrue
undefinednull-0+0NaN''
truefalsenew Boolean(false)true
trueobj1 && obj2true

js转换规则不同场景应用

什么时候自动转换为string类型

  • 在没有对象的前提下
    字符串的自动转换,主要发生在字符串的加法运算时。当一个值为字符串,另一个值为非字符串,则后者转为字符串。
  • 当有对象且与对象+时候

对下面'2'+obj2详细举例说明如下:

  1. 左边为string,ToPrimitive原始值转换后不发生变化
  2. 右边转化时同样按照ToPrimitive进行原始值转换,由于指定的type是number,进行ToPrimitive转化调用obj2.valueof(),得到的不是原始值,进行第三步
  3. 调用toString() return 'a'
  4. 符号两边存在string,而且是+号运算符则都采用String规则转换为string类型进行拼接
  5. 输出结果2a

对下面'2'+obj1详细举例说明如下:

  1. 左边为string,ToPrimitive转换为原始值后不发生变化
  2. 右边转化时同样按照ToPrimitive进行原始值转换,由于指定的type是number,进行ToPrimitive转化调用obj2.valueof(),得到{ a: 1, b: 2}
  3. 调用toString() return [object Object]
  4. 符号两边存在string,而且是+号运算符则都采用String规则转换为string类型进行拼接
  5. 输出结果2[object Object]

代码中几种特殊对象的转换规则基本相同,就不一一说明,大家可以想一下流程。

注意:不管是对象还不是对象,都有一个转换为原始值的过程,也就是ToPrimitive转换,只不过原始类型转换后不发生变化,对象类型才会发生具体转换。

什么时候自动转换为Number类型

  • 有加法运算符,但是无String类型的时候,都会优先转换为Number类型
    例子:
  • 除了加法运算符,其他运算符都会把运算自动转成数值。例子:

注意:null转为数值时为0,而undefined转为数值时为NaN。

判断等号也放在Number里面特殊说明

== 抽象相等比较与+运算符不同,不再是String优先,而是Nuber优先。 下面列举x == y的例子

  1. 如果x,y均为number,直接比较 没什么可解释的了
  1. 如果存在对象,ToPrimitive() type为number进行转换,再进行后面比较
  1. 存在boolean,按照ToNumber将boolean转换为1或者0,再进行后面比较

4.如果x为string,y为number,x转成number进行比较

什么时候进行布尔转换

  • 布尔比较时
  • if(obj) , while(obj) 等判断时或者 三元运算符只能够包含布尔值

条件部分的每个值都相当于false,使用否定运算符后,就变成了true

抽象相等

ES5规范11.9.3节的“抽象相等比较算法”定义了==运算符的行为。该算法简单而又全面,涵盖了所有可能出现的类型组合,以及它们进行强制类型转换的方式。

其他类型和布尔类型之间的相等比较

==最容易出错的一个地方是true和false与其他类型之间的相等比较。

结果是false,这让人很容易掉坑里。如果严格按照“抽象相等比较算法”,这个结果也就是意料之中的。

根据第7条规则,若Type(y)为Boolean, 返回比较x == ToNumber(y)的结果,即返回'42' == 1,结果为false。

很奇怪吧?所以无论什么情况下都不要使用== true和== false。

还有一个坑常常被提到:

""、"\n"(或者" "等其他空格组合)等空字符串被ToNumber强制类型转换为0。

再来看看那些“短”的地方:

其中有4种情况涉及== false,之前我们说过应该避免,所以还剩下后面3种。

这些特殊情况会导致各种问题,使用中要多加小心。我们要对==两边的值认真推敲,以下两个原则可以让我们有效地避免出错。

  • 如果两边的值中有true或者false,千万不要使用==
  • 如果两边的值中有[]、""、或者0,尽量不要使用==

隐式强制转换在部分情况下确实很危险,为了安全起见就要使用===

js中的数据类型判断

面试官问:如何判断数据类型?怎么判断一个值到底是数组类型还是对象?

三种方式,分别为 typeof、instanceof 和 Object.prototype.toString()

typeof

通过 typeof操作符来判断一个值属于哪种基本类型

上面代码的输出结果可以看出,

  1. null 的判定有误差,得到的结果 如果使用 typeof,null得到的结果是object
  2. 操作符对对象类型及其子类型,例如函数(可调用对象)、数组(有序索引对象)等进行判定,则除了函数都会得到 object 的结果。

综上可以看出typeOf对于判断类型还有一些不足,在对象的子类型和null情况下。

instanceof

通过 instanceof 操作符也可以对对象类型进行判定,其原理就是测试构造函数的  prototype 是否出现在被检测对象的原型链上。

复制代码注意:instanceof 也不是万能的。 举个例子:

在这个例子中,arr 数组相当于 new Array() 出的一个实例,所以 arr.proto === Array.prototype,又因为 Array 属于 Object 子类型,即 Array.prototype.proto === Object.prototype,所以 Object 构造函数在 arr 的原型链上。所以 instanceof 仍然无法优雅的判断一个值到底属于数组还是普通对象。

还有一点需要说明下,有些开发者会说 Object.prototype.proto === null,岂不是说 arr instanceof null 也应该为 true,这个语句其实会报错提示右侧参数应该为对象,这也印证 typeof null 的结果为 object 真的只是javascript中的一个 bug 。

Object.prototype.toString() 可以说是判定 JavaScript 中数据类型的终极解决方法了,具体用法请看以下代码:

我们可以发现该方法在传入任何类型的值都能返回对应准确的对象类型。用法虽简单明了,但其中有几个点需要理解清楚:

  • 该方法本质就是依托Object.prototype.toString() 方法得到对象内部属性 [[Class]]
  • 传入原始类型却能够判定出结果是因为对值进行了包装
  • null 和 undefined 能够输出结果是内部实现有做处理

NaN相关总结

NaN的概念

NaN 是一个全局对象的属性,NaN 是一个全局对象的属性,NaN是一种特殊的Number类型

什么时候返回NaN (开篇第二道题也得到解决)

  • 无穷大除以无穷大
  • 给任意负数做开方运算
  • 算数运算符与不是数字或无法转换为数字的操作数一起使用
  • 字符串解析成数字

一些例子:

nullundefined
===

它们不相等,因为它们属于不同的类型。

==

JavaScript 存在一个特殊的规则,会判定它们相等。他们俩就像“一对恋人”,仅仅等于对方而不等于其他任何的值(只在非严格相等下成立)。

< > <= >=
null/undefinednull0undefinedNaN

下面让我们看看,这些规则会带来什么有趣的现象。同时更重要的是,我们需要从中学会如何远离这些特性带来的“陷阱”。

奇怪的结果:null vs 0

通过比较 null 和 0 可得:

是的,上面的结果完全打破了你对数学的认识。在最后一行代码显示“null 大于等于 0”的情况下,前两行代码中一定会有一个是正确的,然而事实表明它们的结果都是 false。

为什么会出现这种反常结果,这是因为相等性检测 == 和普通比较符 > < >= <= 的代码逻辑是相互独立的。进行值的比较时,null 会被转化为数字,因此它被转化为了 0。这就是为什么(3)中 null >= 0 返回值是 true,(1)中 null > 0 返回值是 false。

另一方面,undefined 和 null 在相等性检测 == 中不会进行任何的类型转换,它们有自己独立的比较规则,所以除了它们之间互等以及与本身相等外,不会等于任何其他的值。这就解释了为什么(2)中 null == 0 会返回 false。

特立独行的 undefined

undefined 不应该被与其他值进行比较:

为何它看起来如此厌恶 0?返回值都是 false!

原因如下:

  • (1) 和 (2) 都返回 false 是因为 undefined 在比较中被转换为了 NaN,而 NaN 是一个特殊的数值型值,它与任何值进行比较都会返回 false。
  • (3) 返回 false 是因为这是一个相等性检测,而 undefined 只与 null 和自己相等,不会与其他值相等。

规避错误

我们为何要研究上述示例?我们需要时刻记得这些古怪的规则吗?不,其实不需要。虽然随着代码写得越来越多,我们对这些规则也都会烂熟于胸,但是我们需要更为可靠的方法来避免潜在的问题:

undefined/null
>= > < <=null/undefinednull/undefined

误区

toString和String的区别

  • toString
  1. toString()可以将数据都转为字符串,但是null和undefined不可以转换。
  1. toString()括号中可以写数字,代表进制
    二进制:.toString(2);
    八进制:.toString(8);
    十进制:.toString(10);
    十六进制:.toString(16);
  • String
  1. String()可以将null和undefined转换为字符串,但是没法转进制字符串

插个小片段 


阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。