1、src 和 href 的区别
href: 是 Hypertext Reference 的缩写,表示超文本引用。用来建立当前元素和文档之间的链接。例如:
<link href="reset.css" rel=”stylesheet“/>
浏览器会识别该文档为 css 文档,并行下载该文档,并且不会停止对当前文档的处理。这也是建议使用 link,而不采用 @import 加载 css 的原因。
src: 是 source 的缩写,src 的内容是页面必不可少的一部分,是引入。src 指向的内容会嵌入到文档中当前标签所在的位置。常用的有:img、script、iframe。例如:
<script src="script.js"></script>
当浏览器解析到该元素时,会暂停浏览器的渲染,直到该资源加载完毕。这也是将js脚本放在底部而不是头部得原因。
简而言之,src 用于替换当前元素;href 用于在当前文档和引用资源之间建立联系。
2、下面代码输出什么
setTimeout(function(){
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
},0)
setImmediate(function() {
console.log('6');
},0)
process.nextTick(function() {
console.log('7');
})
new Promise(function(resolve) {
console.log('8')
resolve();
}).then(function(){
console.log('9')
})
console.log('1');
setTimeout(function() {
console.log('10');
process.nextTick(function() {
console.log('11');
})
new Promise(function(resolve) {
console.log('12');
resolve();
}).then(function() {
console.log('13')
})
})
答案:8 1 7 9 2 4 3 5 10 12 11 13 6
Tips:
1、异步事件包括本轮和次轮事件循环,本轮循环先于次轮循环执行,而Promise.then()是本轮事件循环,而setTimeout和setInterval是次轮事件循环。
2、无论nextTick与setImmediate谁在前谁在后,一定是nextTick先执行
3、process.nextTick()是一个特殊的异步API,他不属于任何的Event Loop阶段。事实上Node在遇到这个API时,Event Loop根本就不会继续进行,会马上停下来执行process.nextTick(),这个执行完后才会继续Event Loop。
3、websocket遵循什么协议请求头的url是什么样的?
概念介绍
- 单工通信:数据传输只允许在一个方向上传输,只能一方发送数据,另一方接收数据并发送。
- 半双工:数据传输允许两个方向上的传输,但在同一时间内,只可以有一方发送或接收数据。
- 全双工:同时可进行双向数据传输。
WebSocket在建立握手时,数据是通过HTTP传输的
WebSocket的协议头的写法有2个,一个是ws://
,另一个是wss://
,它们的区别就是后者相当于https,是加密的。如果url没有加端口号,当协议头为ws时默认为80端口,当协议头为wss时默认为443端口。
websocket头详解
请求头详解
Upgrade: 向服务器指定协议类型,告诉web服务器当前使用的是websocket协议
Sec-WebSocket-Key:是一个 Base64 encode 的值,这个是浏览器随机生成的
Sec-WebSocket-Version:websocket协议版本
响应头详解(web服务返回状态码101表示协议切换成功)
Sec-WebSocket-Accept: 是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。用来证明客户端和服务器之间能进行通信了。
4、ts的interface和type什么区别?
interface:接口,TS 设计出来主要用于定义【对象类型】,可以对【对象】的形状进行描述。
type
类型别名可以起到类似接口的作用。但是,有一些细微的差别。主要区别在于 type 一旦定义就不能再添加新的属性,而 interface 总是可扩展的。
Tips:
1、如果需要被 extends 或者 implements, 则尽量使用接口。
2、如果需要使用联合类型或者元组类型,类型别名会更合适。
3、如果是定义对象或函数,则都可以。
4、如果实在不想选择的话,就能用interface实现,用interface,如果不能就用type。
5、编一个promise函数
function MyPromise(fn) {
// promise 的状态
this.promiseState = "pendding";
// promise 的值
this.promiseResult = undefined;
// 定义一个函数对象,用来注册then中的callback
this.thenCallback = undefined;
this.catchCallback = undefined;
var resolve = (value) => {
// 更改promise的状态和值
if (this.promiseState == "pendding") {
this.promiseState = "fulfilled";
this.promiseResult = value;
// 判断value是否是一个MyPromise对象,如果是就使用自己定义的then
if (value instanceof MyPromise) {
value.then((res) => {
if (this.thenCallback) {
this.thenCallback(res);
}
});
} else {
setTimeout(() => {
if (this.thenCallback) {
this.thenCallback(value);
}
});
}
}
};
var reject = (errValue) => {
if (this.promiseState == "pendding") {
this.promiseState = "rejected";
this.promiseResult = errValue;
// 判断写没写catch()
setTimeout(() => {
console.log(this.catchCallback);
if (this.catchCallback) {
this.catchCallback(errValue);
} else if (this.thenCallback) {
this.thenCallback(errValue);
} else {
throw "catch is not defined!!!!";
}
});
}
};
if (fn) {
fn(resolve, reject);
}
}
MyPromise.prototype.then = function (callback) {
return new MyPromise((resolve, reject) => {
this.thenCallback = (value) => {
// 在使用链式调用的时候,可能第一个调用的不是catch
// 使用我们在做检测时会借助then来将catch的信息向下传递
// 所以我们检测到触发thenCallback的对象是rejected时
// 我们就继续调用下一个reject
if (this.promiseState == "rejected") {
reject(value);
} else {
var res = callback(value);
// 这里防止中间返回是一个promise对象它会继续找then,直接让他调用reject
if (res instanceof MyPromise && res.promiseState == "rejected") {
res.catch((errValue) => {
reject(errValue);
});
} else {
// 这里定义给变量res在调用resolve是为解决.then()的链式调用
resolve(res);
}
}
};
});
};
MyPromise.prototype.catch = function (callback) {
return new MyPromise((resolve, reject) => {
this.catchCallback = (errValue) => {
var res = callback(errValue);
reject(errValue);
};
});
};
// 封装一个MyPromise.resolve的快捷调用
MyPromise.resolve = (value) => {
return new MyPromise((resolve, reject) => {
resolve(value);
});
};
MyPromise.reject = (errValue) => {
return new MyPromise((resolve, reject) => {
reject(errValue);
});
};
MyPromise.all = (promiseArr) => {
let resArr = [];
return new MyPromise((resolve, reject) => {
promiseArr.forEach((item, index) => {
item
.then((res) => {
resArr[index] = res;
var allResolve = promiseArr.every((_item) => {
return _item.promiseState == "fulfilled";
});
// 判断传过来的数组中所有promise对象状态都已完成
if (allResolve) {
resolve(resArr);
}
})
.catch((err) => {
reject(err);
});
});
});
};
MyPromise.race = (promiseArr) => {
let resArr = [];
return new MyPromise((resolve, reject) => {
promiseArr.forEach((item, index) => {
item
.then((res) => {
resolve(res);
})
.catch((err) => {
reject(err);
});
});
});
};