betway必威亚洲官网面试中常见算法问题详解,5分钟从入门到精通

二进制转换

通过某个递归函数将输入的数字转化为二进制字符串:

JavaScript

decimalToBinary(3); // 11 decimalToBinary(8); // 1000
decimalToBinary(1000); // 1111101000 function decimalToBinary(digit) {
if(digit >= 1) { // If digit is not divisible by 2 then recursively
return proceeding // binary of the digit minus 1, 1 is added for the
leftover 1 digit if (digit % 2) { return decimalToBinary((digit – 1) /
2) + 1; } else { // Recursively return proceeding binary digits return
decimalToBinary(digit / 2) + 0; } } else { // Exit condition return ”;
} }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
decimalToBinary(3); // 11
decimalToBinary(8); // 1000
decimalToBinary(1000); // 1111101000
 
function decimalToBinary(digit) {
  if(digit >= 1) {
    // If digit is not divisible by 2 then recursively return proceeding
    // binary of the digit minus 1, 1 is added for the leftover 1 digit
    if (digit % 2) {
      return decimalToBinary((digit – 1) / 2) + 1;
    } else {
      // Recursively return proceeding binary digits
      return decimalToBinary(digit / 2) + 0;
    }
  } else {
    // Exit condition
    return ”;
  }
}

2、数据分片例子

直接看例子更形象些。下面例子来自MDN,可以很好地演示数据的分片。客户端向服务端两次发送消息,服务端收到消息后回应客户端,这里主要看客户端往服务端发送的消息。

第一条消息

FIN=1,
表示是当前消息的最后一个数据帧。服务端收到当前数据帧后,可以处理消息。opcode=0x1,表示客户端发送的是文本类型。

第二条消息

  1. FIN=0,opcode=0x1,表示发送的是文本类型,且消息还没发送完成,还有后续的数据帧。
  2. FIN=0,opcode=0x0,表示消息还没发送完成,还有后续的数据帧,当前的数据帧需要接在上一条数据帧之后。
  3. FIN=1,opcode=0x0,表示消息已经发送完成,没有后续的数据帧,当前的数据帧需要接在上一条数据帧之后。服务端可以将关联的数据帧组装成完整的消息。

Client: FIN=1, opcode=0x1, msg=”hello” Server: (process complete message
immediately) Hi. Client: FIN=0, opcode=0x1, msg=”and a” Server:
(listening, new message containing text started) Client: FIN=0,
opcode=0x0, msg=”happy new” Server: (listening, payload concatenated to
previous message) Client: FIN=1, opcode=0x0, msg=”year!” Server:
(process complete message) Happy new year to you too!

1
2
3
4
5
6
7
8
Client: FIN=1, opcode=0x1, msg="hello"
Server: (process complete message immediately) Hi.
Client: FIN=0, opcode=0x1, msg="and a"
Server: (listening, new message containing text started)
Client: FIN=0, opcode=0x0, msg="happy new"
Server: (listening, payload concatenated to previous message)
Client: FIN=1, opcode=0x0, msg="year!"
Server: (process complete message) Happy new year to you too!

GitHub开源

在GitHub开源了:WebFrontEndStack

 

数组

2、需要学习哪些东西

对网络应用层协议的学习来说,最重要的往往就是连接建立过程数据交换教程。当然,数据的格式是逃不掉的,因为它直接决定了协议本身的能力。好的数据格式能让协议更高效、扩展性更好。

下文主要围绕下面几点展开:

  1. 如何建立连接
  2. 如何交换数据
  3. 数据帧格式
  4. 如何维持连接

爆栈三部曲

  •  Web前端开发大系概览
    (前端开发技术栈)
     ,包含大约180个技术点
  •  数据库开发大系技术栈
    (300多技术点)
  •  .NET技术大系概览
    (迄今为止最全的.NET技术栈)

阐述下 JavaScript 中的变量提升

所谓提升,顾名思义即是 JavaScript
会将所有的声明提升到当前作用域的顶部。这也就意味着我们可以在某个变量声明前就使用该变量,不过虽然
JavaScript 会将声明提升到顶部,但是并不会执行真的初始化过程。

十一、相关链接

RFC6455:websocket规范
https://tools.ietf.org/html/r…

规范:数据帧掩码细节
https://tools.ietf.org/html/r…

规范:数据帧格式
https://tools.ietf.org/html/r…

server-example
https://github.com/websockets…

编写websocket服务器
https://developer.mozilla.org…

对网络基础设施的攻击(数据掩码操作所要预防的事情)
https://tools.ietf.org/html/r…

Talking to Yourself for Fun and Profit(含有攻击描述)
http://w2spconf.com/2011/pape…

What is Sec-WebSocket-Key for?
https://stackoverflow.com/que…

10.3. Attacks On Infrastructure (Masking)
https://tools.ietf.org/html/r…

Talking to Yourself for Fun and Profit
http://w2spconf.com/2011/pape…

Why are WebSockets masked?
https://stackoverflow.com/que…

How does websocket frame masking protect against cache poisoning?
https://security.stackexchang…

What is the mask in a WebSocket frame?
https://stackoverflow.com/que…

1 赞 3 收藏 1
评论

betway必威亚洲官网 1

Web前端开发技术栈

现在流行一个说法,是Full Stack
(全栈),简单地说是万金油,说得体面一点就是前端、后台、存储、架构等都懂,我觉得我不是全栈,而是爆栈(stack
overflow),开玩笑了。。。。

这个Web前端开发技术栈,大约20个层级,大约100个技术点,从底层一直到最顶层:

  • 浏览器
  • 渲染引擎、JavaScript引擎
  • HTML/JavaScript/CSS三支柱
  • 编辑器
  • 编译任务
  • 编译工具
  • 打包、调试、质量
  • 测试
  • JS基础类库
  • JS类库
  • UI框架
  • CSS预处理器
  • 模板
  • 现代化
  • 安全/模式
  • 中间语言
  • 跨平台解决方案

这个图表里的分类未必准确,相关技术也难免会有遗漏,欢迎大家指点以便不断改进。

Web前端技术实在太繁多限于篇幅,,这里没有罗列一些技术。

以下是预览图:

betway必威亚洲官网 2

点击查看原尺寸大图

数组交集

给定两个数组,要求求出两个数组的交集,注意,交集中的元素应该是唯一的。

JavaScript

var firstArray = [2, 2, 4, 1]; var secondArray = [1, 2, 0, 2];
intersection(firstArray, secondArray); // [2, 1] function
intersection(firstArray, secondArray) { // The logic here is to create a
hashmap with the elements of the firstArray as the keys. // After that,
you can use the hashmap’s O(1) look up time to check if the element
exists in the hash // If it does exist, add that element to the new
array. var hashmap = {}; var intersectionArray = [];
firstArray.forEach(function(element) { hashmap[element] = 1; }); //
Since we only want to push unique elements in our case… we can
implement a counter to keep track of what we already added
secondArray.forEach(function(element) { if (hashmap[element] === 1) {
intersectionArray.push(element); hashmap[element]++; } }); return
intersectionArray; // Time complexity O(n), Space complexity O(n) }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var firstArray = [2, 2, 4, 1];
var secondArray = [1, 2, 0, 2];
 
intersection(firstArray, secondArray); // [2, 1]
 
function intersection(firstArray, secondArray) {
  // The logic here is to create a hashmap with the elements of the firstArray as the keys.
  // After that, you can use the hashmap’s O(1) look up time to check if the element exists in the hash
  // If it does exist, add that element to the new array.
 
  var hashmap = {};
  var intersectionArray = [];
 
  firstArray.forEach(function(element) {
    hashmap[element] = 1;
  });
 
  // Since we only want to push unique elements in our case… we can implement a counter to keep track of what we already added
  secondArray.forEach(function(element) {
    if (hashmap[element] === 1) {
      intersectionArray.push(element);
      hashmap[element]++;
    }
  });
 
  return intersectionArray;
 
  // Time complexity O(n), Space complexity O(n)
}

3、掩码算法

掩码键(Masking-key)是由客户端挑选出来的32位的随机数。掩码操作不会影响数据载荷的长度。掩码、反掩码操作都采用如下算法:

首先,假设:

  • original-octet-i:为原始数据的第i字节。
  • transformed-octet-i:为转换后的数据的第i字节。
  • j:为i mod 4的结果。
  • masking-key-octet-j:为mask key第j字节。

算法描述为: original-octet-i 与 masking-key-octet-j 异或后,得到
transformed-octet-i。

j = i MOD 4
transformed-octet-i = original-octet-i XOR masking-key-octet-j

问题

大家是否想过:

  • Web前端开发究竟包含哪些技术呢?
  • 我所掌握的技术这个子集,在Web前端技术大系这个超集里面占的比例是多少呢?
  • 我究竟还没有掌握多少Web前端技术呢?
  • 面试的时候会考哪些技术呢?

相信很多网友看过我之前写的.NET技术大系概览
(迄今为止最全的.NET技术栈)
,一个简单易懂的栈图可以概括.NET这个庞大的技术生态圈里面基础技术:

betway必威亚洲官网 3

 

还有数据库技术栈:

betway必威亚洲官网 4

那么,Web前端开发是否也应该有这样的技术栈概览图呢?

搜索了很久,没有找到一个符合我要求的“较为全面”地表述Web前端技术大系的图表。

互联网上来去都是那几个简单的,譬如这个:

betway必威亚洲官网 5

或者这个:

betway必威亚洲官网 6

或者这个:

betway必威亚洲官网 7

不过这些都远远没有高度概括整个Web前端开发技术,和我需要的不一样。

解释下 null 与 undefined 的区别

JavaScript 中,null 是一个可以被分配的值,设置为 null
的变量意味着其无值。而 undefined
则代表着某个变量虽然声明了但是尚未进行过任何赋值。

3、运行结果

可分别查看服务端、客户端的日志,这里不展开。

服务端输出:

server: receive connection. server: received hello

1
2
server: receive connection.
server: received hello

客户端输出:

client: ws connection is open client: received world

1
2
client: ws connection is open
client: received world

Web前端开发大系概览 (前端开发技术栈)

2015/08/12 · JavaScript
· Web开发

本文作者: 伯乐在线 –
灵感之源
。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

解释下什么是 Event Bubbling 以及如何避免

Event Bubbling
即指某个事件不仅会触发当前元素,还会以嵌套顺序传递到父元素中。直观而言就是对于某个子元素的点击事件同样会被父元素的点击事件处理器捕获。避免
Event Bubbling 的方式可以使用event.stopPropagation() 或者 IE 9
以下使用event.cancelBubble

1、代理缓存污染攻击

下面摘自2010年关于安全的一段讲话。其中提到了代理服务器在协议实现上的缺陷可能导致的安全问题。猛击出处。

“We show, empirically, that the current version of the WebSocket
consent mechanism is vulnerable to proxy cache poisoning attacks. Even
though the WebSocket handshake is based on HTTP, which should be
understood by most network intermediaries, the handshake uses the
esoteric “Upgrade” mechanism of HTTP [5]. In our experiment, we find
that many proxies do not implement the Upgrade mechanism properly,
which causes the handshake to succeed even though subsequent traffic
over the socket will be misinterpreted by the proxy.”[TALKING]
Huang, L-S., Chen, E., Barth, A., Rescorla, E., and C.

Jackson, “Talking to Yourself for Fun and Profit”, 2010,

1
          Jackson, "Talking to Yourself for Fun and Profit", 2010,

在正式描述攻击步骤之前,我们假设有如下参与者:

  • 攻击者、攻击者自己控制的服务器(简称“邪恶服务器”)、攻击者伪造的资源(简称“邪恶资源”)
  • 受害者、受害者想要访问的资源(简称“正义资源”)
  • 受害者实际想要访问的服务器(简称“正义服务器”)
  • 中间代理服务器

攻击步骤一:

  1. 攻击者浏览器 向 邪恶服务器
    发起WebSocket连接。根据前文,首先是一个协议升级请求。
  2. 协议升级请求 实际到达 代理服务器
  3. 代理服务器 将协议升级请求转发到 邪恶服务器
  4. 邪恶服务器 同意连接,代理服务器 将响应转发给 攻击者

由于 upgrade 的实现上有缺陷,代理服务器
以为之前转发的是普通的HTTP消息。因此,当协议服务器
同意连接,代理服务器 以为本次会话已经结束。

攻击步骤二:

  1. 攻击者 在之前建立的连接上,通过WebSocket的接口向 邪恶服务器
    发送数据,且数据是精心构造的HTTP格式的文本。其中包含了 正义资源
    的地址,以及一个伪造的host(指向正义服务器)。(见后面报文)
  2. 请求到达 代理服务器 。虽然复用了之前的TCP连接,但 代理服务器
    以为是新的HTTP请求。
  3. 代理服务器邪恶服务器 请求 邪恶资源
  4. 邪恶服务器 返回 邪恶资源代理服务器 缓存住
    邪恶资源(url是对的,但host是 正义服务器 的地址)。

到这里,受害者可以登场了:

  1. 受害者 通过 代理服务器 访问 正义服务器正义资源
  2. 代理服务器 检查该资源的url、host,发现本地有一份缓存(伪造的)。
  3. 代理服务器邪恶资源 返回给 受害者
  4. 受害者 卒。

附:前面提到的精心构造的“HTTP请求报文”。

Client → Server: POST /path/of/attackers/choice HTTP/1.1 Host:
host-of-attackers-choice.com Sec-WebSocket-Key: Server → Client:
HTTP/1.1 200 OK Sec-WebSocket-Accept:

1
2
3
4
5
Client → Server:
POST /path/of/attackers/choice HTTP/1.1 Host: host-of-attackers-choice.com Sec-WebSocket-Key:
Server → Client:
HTTP/1.1 200 OK
Sec-WebSocket-Accept:

前言

互联网建立50多年了,网站开发技术日新月异,但web前端始终离不开浏览器,最终还是HTML+JavaScript+CSS这3个核心,围绕这3个核心而开发出来大量技术框架/解决方案。

我从2000年初开始做网站开发,使用的技术不断迭代,一些消失了,更多的出现了。

最近写过  .NET技术大系概览
(迄今为止最全的.NET技术栈) 
,相信很多网友感叹掌握的.NET技术远没有这个技术栈里面所描述的多。

找出整型数组中乘积最大的三个数

给定一个包含整数的无序数组,要求找出乘积最大的三个数。

JavaScript

var unsorted_array = [-10, 7, 29, 30, 5, -10, -70];
computeProduct(unsorted_array); // 21000 function sortIntegers(a, b) {
return a – b; } // greatest product is either (min1 * min2 * max1 ||
max1 * max2 * max3) function computeProduct(unsorted) { var
sorted_array = unsorted.sort(sortIntegers), product1 = 1, product2 = 1,
array_n_element = sorted_array.length – 1; // Get the product of
three largest integers in sorted array for (var x = array_n_element; x
> array_n_element – 3; x–) { product1 = product1 *
sorted_array[x]; } product2 = sorted_array[0] *
sorted_array[1] * sorted_array[array_n_element]; if (product1
> product2) return product1; return product2 };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var unsorted_array = [-10, 7, 29, 30, 5, -10, -70];
 
computeProduct(unsorted_array); // 21000
 
function sortIntegers(a, b) {
  return a – b;
}
 
// greatest product is either (min1 * min2 * max1 || max1 * max2 * max3)
function computeProduct(unsorted) {
  var sorted_array = unsorted.sort(sortIntegers),
    product1 = 1,
    product2 = 1,
    array_n_element = sorted_array.length – 1;
 
  // Get the product of three largest integers in sorted array
  for (var x = array_n_element; x > array_n_element – 3; x–) {
      product1 = product1 * sorted_array[x];
  }
  product2 = sorted_array[0] * sorted_array[1] * sorted_array[array_n_element];
 
  if (product1 > product2) return product1;
 
  return product2
};

1、服务端

代码如下,监听8080端口。当有新的连接请求到达时,打印日志,同时向客户端发送消息。当收到到来自客户端的消息时,同样打印日志。

var app = require(‘express’)(); var server =
require(‘http’).Server(app); var WebSocket = require(‘ws’); var wss =
new WebSocket.Server({ port: 8080 }); wss.on(‘connection’, function
connection(ws) { console.log(‘server: receive connection.’);
ws.on(‘message’, function incoming(message) { console.log(‘server:
received: %s’, message); }); ws.send(‘world’); }); app.get(‘/’, function
(req, res) { res.sendfile(__dirname + ‘/index.html’); });
app.listen(3000);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var app = require(‘express’)();
var server = require(‘http’).Server(app);
var WebSocket = require(‘ws’);
 
var wss = new WebSocket.Server({ port: 8080 });
 
wss.on(‘connection’, function connection(ws) {
    console.log(‘server: receive connection.’);
    
    ws.on(‘message’, function incoming(message) {
        console.log(‘server: received: %s’, message);
    });
 
    ws.send(‘world’);
});
 
app.get(‘/’, function (req, res) {
  res.sendfile(__dirname + ‘/index.html’);
});
 
app.listen(3000);

交互式浏览

点击 这里 查看基于HTML的交互式图示
(鼠标拖动/滚轮缩放)

1 赞 8 收藏
评论

解释下 Prototypal Inheritance 与 Classical Inheritance 的区别

在类继承中,类是不可变的,不同的语言中对于多继承的支持也不一样,有些语言中还支持接口、final、abstract
的概念。而原型继承则更为灵活,原型本身是可以可变的,并且对象可能继承自多个原型。

3、Sec-WebSocket-Accept的计算

Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来。

计算公式为:

  1. Sec-WebSocket-Key258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
  2. 通过SHA1计算出摘要,并转成base64字符串。

伪代码如下:

>toBase64( sha1( Sec-WebSocket-Key +
258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ) )

1
>toBase64( sha1( Sec-WebSocket-Key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 )  )

验证下前面的返回结果:

const crypto = require(‘crypto’); const magic =
‘258EAFA5-E914-47DA-95CA-C5AB0DC85B11’; const secWebSocketKey =
‘w4v7O6xFTi36lq3RNcgctw==’; let secWebSocketAccept =
crypto.createHash(‘sha1’) .update(secWebSocketKey + magic)
.digest(‘base64’); console.log(secWebSocketAccept); //
Oy4NRAQ13jhfONC7bP8dTKb4PTU=

1
2
3
4
5
6
7
8
9
10
const crypto = require(‘crypto’);
const magic = ‘258EAFA5-E914-47DA-95CA-C5AB0DC85B11’;
const secWebSocketKey = ‘w4v7O6xFTi36lq3RNcgctw==’;
 
let secWebSocketAccept = crypto.createHash(‘sha1’)
    .update(secWebSocketKey + magic)
    .digest(‘base64’);
 
console.log(secWebSocketAccept);
// Oy4NRAQ13jhfONC7bP8dTKb4PTU=

关于作者:灵感之源

betway必威亚洲官网 8

智能实验室创始人。做过开源,写过千万下载量软件,爱美剧电影音乐美女。定居澳洲悉尼。twitter加unruledboy。移民澳新的去freeoz论坛中国域名hioz

个人主页 ·
我的文章 ·
6 ·
  

betway必威亚洲官网 1

使用两个栈实现入队与出队

JavaScript

var inputStack = []; // First stack var outputStack = []; // Second
stack // For enqueue, just push the item into the first stack function
enqueue(stackInput, item) { return stackInput.push(item); } function
dequeue(stackInput, stackOutput) { // Reverse the stack such that the
first element of the output stack is the // last element of the input
stack. After that, pop the top of the output to // get the first element
that was ever pushed into the input stack if (stackOutput.length <=
0) { while(stackInput.length > 0) { var elementToOutput =
stackInput.pop(); stackOutput.push(elementToOutput); } } return
stackOutput.pop(); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var inputStack = []; // First stack
var outputStack = []; // Second stack
 
// For enqueue, just push the item into the first stack
function enqueue(stackInput, item) {
  return stackInput.push(item);
}
 
function dequeue(stackInput, stackOutput) {
  // Reverse the stack such that the first element of the output stack is the
  // last element of the input stack. After that, pop the top of the output to
  // get the first element that was ever pushed into the input stack
  if (stackOutput.length <= 0) {
    while(stackInput.length > 0) {
      var elementToOutput = stackInput.pop();
      stackOutput.push(elementToOutput);
    }
  }
 
  return stackOutput.pop();
}

五、数据帧格式

客户端、服务端数据的交换,离不开数据帧格式的定义。因此,在实际讲解数据交换之前,我们先来看下WebSocket的数据帧格式。

WebSocket客户端、服务端通信的最小单位是帧(frame),由1个或多个帧组成一条完整的消息(message)。

  1. 发送端:将消息切割成多个帧,并发送给服务端;
  2. 接收端:接收消息帧,并将关联的帧重新组装成完整的消息;

本节的重点,就是讲解数据帧的格式。详细定义可参考 RFC6455
5.2节 。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

标签:, ,
网站地图xml地图