线性顺序存储结构和链式存储结构有什么区别?以及优缺点。

顺序存储结构和链式存储结构的区别

链表存储结构的内存地址不一定是连续的,但顺序存储结构的内存地址一定是连续的;
链式存储适用于在较频繁地插入、删除、更新元素时,而顺序存储结构适用于频繁查询时使用。

顺序存储结构和链式存储结构的优缺点:

空间上

顺序比链式节约空间。是因为链式结构每一个节点都有一个指针存储域。

存储操作上:

顺序支持随机存取,方便操作

插入和删除上:

链式的要比顺序的方便(因为插入的话顺序表也很方便,问题是顺序表的插入要执行更大的空间复杂度,包括一个从表头索引以及索引后的元素后移,而链表是索引后,插入就完成了)
例如:当你在字典中查询一个字母j的时候,你可以选择两种方式,第一,顺序查询,从第一页依次查找直到查询到j。第二,索引查询,从字典的索引中,直接查出j的页数,直接找页数,或许是比顺序查询最快的。


2018-8-21 请说说你对执行 JS 代码时产生的执行上下文的理解

当执行 JS 代码时,会产生三种执行上下文
全局执行上下文
函数执行上下文
eval 执行上下文
每个执行上下文中都有三个重要的属性
变量对象(VO),包含变量、函数声明和函数的形参,该属性只能在全局上下文中访问
作用域链(JS 采用词法作用域,也就是说变量的作用域是在定义时就决定了)
this
var a = 10
function foo(i) {
  var b = 20
}
foo()

对于上述代码,执行栈中有两个上下文:全局上下文和函数 foo 上下文。

stack = [
    globalContext,
    fooContext
]

对于全局上下文来说,VO 大概是这样的

globalContext.VO === globe
globalContext.VO = {
    a: undefined,
    foo: ,
}

对于函数 foo 来说,VO 不能访问,只能访问到活动对象(AO)

fooContext.VO === foo.AO
fooContext.AO {
    i: undefined,
    b: undefined,
    arguments: <>
}
// arguments 是函数独有的对象(箭头函数没有)
// 该对象是一个伪数组,有 `length` 属性且可以通过下标访问元素
// 该对象中的 `callee` 属性代表函数本身
// `caller` 属性代表函数的调用者
对于作用域链,可以把它理解成包含自身变量对象和上级变量对象的列表,通过 [[Scope]] 属性查找上级变量

fooContext.[[Scope]] = [
    globalContext.VO
]
fooContext.Scope = fooContext.[[Scope]] + fooContext.VO
fooContext.Scope = [
    fooContext.VO,
    globalContext.VO
]
接下来让我们看一个老生常谈的例子,var

b() // call b
console.log(a) // undefined

var a = 'Hello world'

function b() {
    console.log('call b')
}
想必以上的输出大家肯定都已经明白了,这是因为函数和变量提升的原因。通常提升的解释是说将声明的代码移动到了顶部,这其实没有什么错误,便于大家理解。但是更准确的解释应该是:在生成执行上下文时,会有两个阶段。第一个阶段是创建的阶段(具体步骤是创建 VO),JS 解释器会找出需要提升的变量和函数,并且给他们提前在内存中开辟好空间,函数的话会将整个函数存入内存中,变量只声明并且赋值为 undefined,所以在第二个阶段,也就是代码执行阶段,我们可以直接提前使用。
在提升的过程中,相同的函数会覆盖上一个函数,并且函数优先于变量提升

b() // call b second

function b() {
    console.log('call b fist')
}
function b() {
    console.log('call b second')
}
var b = 'Hello world'

2018-8-23 请说说你对Event loop的理解?浏览器中的Event loop和Node中的Event loop的异同?

浅析Nodejs Event Loop

为什么 0.1 + 0.2 != 0.3? 如何解决? (2018-8-24)

JS是不区分整数和浮点数的,JS采用的是IEEE 754标准定义的64位浮点格式表示数字,所以JS中的所有数字都是浮点数。按照JS的数字格式,整数有的范围是-2^53 ~ 2^53,而且只能表示有限个浮点数,能表示的个数为2^64 − 2^53 + 3个。至于为什么是这个范围,可以具体看看《JavaScript 中的数字》这篇文章也解下。而我们都知道,浮点数的个数是无限的,这就导致了JS不能精确表达所有的浮点数,而只能是一个近似值。

什么是Service Worker?如何使用?(2018-8-27)

html5的API service worker是一个浏览器背后运行的脚步,独立于web页面

Service Worker 基于 Web Worker 事件驱动。

Service Worker 同样可以在浏览器后台挂起新线程,来缓解 JavaScript 的单线程问题。并且,我们可以用 Service Worker 拦截网络请求进行本地缓存或请求转发,相当于充当服务端与浏览器、浏览器与 Web 应用程序之间的代理服务器。

Service Worker 带来了速度,极大的提高了用户体验。

Service Worker 可有效加快重复访问网络应用的速度。
拥有拦截请求、消息推送、静默更新、地理围栏等服务。
可以在客户端通过 indexedDB API 保存持久化信息。

Service Worker 大量使用 Promise 对象。

因为通常 Service Worker 会等待响应后继续,并根据响应返回一个成功或者失败的操作。Promise 非常适合这种场景。

零、Service Worker 的生命周期。

所谓生命周期,包括 Service Worker 的注册、安装、激活、控制和销毁时的全部过程。我们需要对 Service Worker 的生命周期有所了解。

Service workers 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步API。 目前该技术通常用来做缓存文件,提高首屏速度,可以试着来实现这个功能。

// // index.js
if 
if (f (navigator.serviceWorkerrker) {
  
  navigator.serviceWorkerrker
    .register("r("sw.js")
 ")
    .then(function(registration) {
         console.log("se("service worker 注册成功");
    })
    .catch(function(err) {
         console.log("se("servcie worker 注册失败");
    });
}
// // sw.js
// 
// 监听 `install` 事件,回调中缓存所需文件
文件
self.addEventListeistener("install", e => {
  
  e.waitUntil(
  (
       caches.open("my("my-cache").then(function(cache) {
      return rn cache.addAll([".(["./"./index.html", "", "./"./index.js"]);"]);
    })
  );
});

// 拦截所有请求事件
// 如果缓存中已经有请求的数据就直接用缓存,否则去请求数据
数据
self.addEventListeistener("fetch", e => {
  
  e.respondWith(
th(
       caches.match(e.r(ch(e.request).th).then(function(response) {
      if (response) {
        return response;
      }
         console.log("fe("fetch source");
    })
  );
});

打开页面,可以在开发者工具中的 Application 看到 Service Worker 已经启动了 在 Cache 中也可以发现我们所需的文件已被缓存

如何进行 Webpack 优化(2018-8-28)

1. 缩小文件搜索范围,配置比如resolve.modules,resolve.modules,resolve.mainFields,resolve.alias ,resolve.extensions ,module.noParse 配置
2. 使用DllPlugin 要给 Web 项目构建接入动态链接库
3.HappyPack 就能让 Webpack 做到这点,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程
4.当 Webpack 有多个 JavaScript 文件需要输出和压缩时,原本会使用 UglifyJS 去一个个挨着压缩再输出, 但是 ParallelUglifyPlugin 则会开启多个子进程,把对多个文件的压缩工作分配给多个子进程去完成
5.可以监听文件的变化,当文件发生变化后可以自动刷新浏览器,从而提高开发效率。
6.(Hot Module Replacement)的技术可在不刷新整个网页的情况下做到超灵敏的实时预览。 原理是当一个源码发生变化时,只重新编译发生变化的模块,再用新输出的模块替换掉浏览器中对应的老模块。
7.Tree Shaking 可以用来剔除 JavaScript 中用不上的死代码。它依赖静态的 ES6 模块化语法,例如通过 import 和 export 导入导出
8.可以使用CommonsChunkPlugin 把多个页面公共的代码抽离成单独的文件进行加载
9.Webpack 内置了强大的分割代码的功能去实现按需加载,可以用import实现路由按需加载。
10.Scope Hoisting 可以让 Webpack 打包出来的代码文件更小、运行的更快, 它又译作 "作用域提升"
11.可以使用可视化分析工具 Webpack Analyse等去分析输出结果,从页进行优化.
12. 对于 Webpack4,打包项目使用 production 模式,这样会自动开启代码压缩
13.优化图片,对于小图可以使用 base64 的方式写入文件中
14. 给打包出来的文件名添加哈希,实现浏览器缓存文件

ES6中 Generator 的实现原理?(2018-5-29)

Generator 实现
Generator 是 ES6 中新增的语法,和 Promise 一样,都可以用来异步编程

// 使用 * 表示这是一个 Generator 函数
// 内部可以通过 yield 暂停代码
// 通过调用 next 恢复执行
function* test() {
  let a = 1 + 2;
  yield 2;
  yield 3;
}
let b = test();
console.log(b.next()); // >  { value: 2, done: false }
console.log(b.next()); // >  { value: 3, done: false }
console.log(b.next()); // >  { value: undefined, done: true }

从以上代码可以发现,加上 * 的函数执行后拥有了 next 函数,也就是说函数执行后返回了一个对象。每次调用 next 函数可以继续执行被暂停的代码。以下是 Generator 函数的简单实现

// cb 也就是编译过的 test 函数
function generator(cb) {
  return (function() {
    var object = {
      next: 0,
      stop: function() {}
    };

    return {
      next: function() {
        var ret = cb(object);
        if (ret === undefined) return { value: undefined, done: true };
        return {
          value: ret,
          done: false
        };
      }
    };
  })();
}
// 如果你使用 babel 编译后可以发现 test 函数变成了这样
function test() {
  var a;
  return generator(function(_context) {
    while (1) {
      switch ((_context.prev = _context.next)) {
        // 可以发现通过 yield 将代码分割成几块
        // 每次执行 next 函数就执行一块代码
        // 并且表明下次需要执行哪块代码
        case 0:
          a = 1 + 2;
          _context.next = 4;
          return 2;
        case 4:
          _context.next = 6;
          return 3;
        // 执行完毕
        case 6:
        case "end":
          return _context.stop();
      }
    }
  });
}

什么是IFC?IFC的作用是什么?

这几个网站有所有完整的概念。
IFC BFC都属于「视觉可视化模型」
视觉格式化模型
MDN web Docs 块格式化上下文
CSS 视觉格式化模型

什么是跨域?常用的跨域方式有哪些?

由于浏览器存在同源策略,请求的 Url 地址的协议、主机名、端口号必须完全相同,否则会产生跨域,同源策略的限制下 cookie 、loclstorage、dom、ajax、IndexDB 等都不允许跨域、form 表单不受同源策略限制
对跨域的理解有一个误区,跨域不是请求没有发送出去或者服务器接收到请求而没有响应,正确的情况是请求发出,服务器响应,由于响应和请求来自不同的域被浏览器拦截了。
跨域的方式有以下几种:
1、jsonp:通过 script 的 src 属性发送请求,传参必须含有 callback 回调的名称,服务器返回函数的调用,接收到响应直接执行;
2、cors:通过服务端设置 Access-Control-Allow-Origin,通常在后端通过白名单设置权限允许固定的域来访问
3、window.postMessage:Hge:H5 API,消息接收方通过 message 事件接收,事件对象 data 属性代表接收的消息,可以通过事件对象的 source 属性 通过 通过 source.postMessage(“ge(“message”, ”, e.origin) 进行) 进行回复
4、可以使用 使用 window.name 和 l 和 和 location.hash 在不同 在不同域的 iframe 页面之间进行消息传递
5、document.domain:如果域:如果域名之间是一二级域名的关系,可以将页面的 面的 document.domain 设置为 设置为一级域名的后半部分,如:,如:baidu.com 实现跨 实现跨域
6、可以使用 websocket 进行跨域,websocek 的协议为 ws:// 或 wss:// 是实时通信,不存在跨域问题。
7、服务器与服务器之间通信不受浏览器同源策略限制,因此不存在跨域问题,可以使用 nginx 或 node 的 http-proxy-middleware 中间件实现作为代理服务器帮助浏览器对请求进行转发,完成与不同域的服务器之间的通信,webpack-dev-server 就是通过 http-proxy-middleware 实现的跨域
详情请看:

你可能感兴趣的:(线性顺序存储结构和链式存储结构有什么区别?以及优缺点。)