八, for循环与 map 的区别
1. foreach 与 for 的区别:
(1),固定长度或者长度不需要计算的时候用for, 不确定长度或者计算长度有损性能的时候用fo reach
(2),foreach用于集合或者数组遍历, for在复杂的循环中效率更高;
(3),对集合进行修改的时候, 用for;
(4),foreach 相比 for 的优势在于对稀疏数组的处理, 会跳过数组中的空位;
2. 数组中foreach 与 map
相同点:
- 都是循环遍历数组中的每一项;
- 每次执行匿名函数都支持 3 个参数,item(当前每一项),index(索引值), arr(原数组)
- 匿名函数中的 this 都是指向window;
- 只能遍历数组;
- 都不会改变原数组;
区别:
map: 返回一个新的数组, 数组中的元素为原始数组调用函数处理后的值; map不会对空数组进行监测, map方法不会改变原始数组;arr 是空数组, 返回也是空数组; 支持 chrome等;
forEach:用来调用数组的每个元素, 将元素传给回调函数; 对于空数组不会调用回调函数; 无论arr 是不是空数组, forEach返回的都是 undefined。
九, 图片自适应拉伸
图片设置 no-repeat, background-size: 100% 100%; 自适应大小;
十,JS 原型链
原型链和原型对象是 js 的核心。
原型:JavaScript 是基于原型的我们创建的每个函数都有一个prototype(原型)属性, 该属性是一个指针, 指向一个对象,该对象的用途是包含可以由特定类型的所有实例共享的属性和方法。(当我们创建一个函数的时候 ,系统会自动分配一个 prototype属性, 用来存储可以让所有实例共享的属性和方法);
- 每个构造函数都有一个 prototype 属性,这个属性指向原型对象;
- 原型对象默认拥有一个constructor 属性,指向他的构造函数;
- 每个对象都拥有一个 _proto_ 隐藏属性,指向它的原型对象;
若已经创建实例, 重写原型会切断实例与原型之间的联系。 重写原型对象时候将constructor指向构造函数。
原型链: 所有的对象都是由他的原型对象继承而来, 而原型对象自己本身也是一个对象,它也有自己的原型对象 , 这样层层上朔,就形成了一个原型链。
- 所有原型链的终点都是Object 函数的 prototype 属性;
- Object.prototype 指向的原型对象也拥有原型, 不过是null, null没有原型;
十一,怎样累加求和
- for 循环累加;
- forEach循环累加;
-
return eval(arr.join("+"))
4. 函数式编程:
function sumArr(arr){
return arr.reduce(function(prev,cur){
return prev + cur;
},0);
}
十二,TypeScript原理
Scanner 扫描器(scanner.ts)
Parser 解析器 (parser.ts)
Binder 绑定器 (binder.ts)
Checker 检查器 (checker.ts)
Emitter 发射器(emitter.ts)
工作原理:
- TypeScript 源码经过扫描器扫描之后会变成一系列 Token;
- 解析器解析token,得到一棵 AST 语法树;
- 绑定器遍历 AST 语法树, 生成一系列Symbol,并将这些 Symbol 连接到对应的节点上去;
- 检查器再次扫描 AST, 检查类型, 并将错误收集起来;
- 发射器根据AST 生成 JavaScript代码;
十三,同步,异步
同步转异步:
- 定时器, setTimeout
- promise
let p = new Promise( res => { resolve(); }); p.then(() => { // 之前的同步操作 })
异步转同步(promise):
// 定义需要异步处理的方法
function getData() {
return new Promise( reslove => {
resolve('resolve');
})
}
async function callback() {
var data = await getData();
// 处理结果
}
十四,数组转对象
- 展开运算符
const arr = ['one', 'two', 'three']; const obj = {...arr}; console.log(obj); // {0: 'one', 1: 'two', 2: 'three'};
- Object.assign()
const arr = [1, 2, 3]; const obj = Object.assign({}, arr); console.log(obj); // {0:1, 1:2, 2:3}
- Object.fromEntries, 把键值对转换为对象
const arr = [['1', 1], ['2', 2], ['3', 3]]; const obj = Object.fromEntried({arr); console.log(obj); // {1:1, 2:2, 3:3}
- forEach, 定义变量循环赋值
十五,对象转数组
- Object.entries();
const obj = {a: 1, b:2, c: 3}; const arr = Object.entries(obj); console.log(arr); // [['a', 1], ['b', 2], ['c', 3]]
- Object.keys()
const obj = {a: 1, b:2, c: 3}; const arr = Object.keys(obj); console.log(arr); // ['a', 'b', 'c']
- Object.values(), 由给定的对象自身可枚举的属性值组成的数组
const obj = {a: 1, b: 2, c: 3}; const arr = Object.values(obj); console.log(arr); // [1, 2, 3]
- Array.from(arr, fn, this), 从一个类似数组对象或可迭代对象创建一个新的, 浅拷贝的数组实例。 参数:
array: 要变化成数组的数组对象或可迭代对象;
fn: 指定了该参数, 新数组中的每个元素都会执行该回调函数;
this:执行回调函数时的this对象;
// 数组对象
const obj = {
0: 'name',
1: 'age',
2: 'sex',
3: 'height,
length: 3
};
const arr = Array.from(obj);
console.log(arr); // ['name', 'age', 'sex']
// 输出3个是因为上面说的length的长度决定了数组的长度
// 可迭代对象
const obj2 = {
0: 'name',
1: 'age',
2: 'sex',
3: 'height'
};
function *createInterator(ojb) {
for( let value in obj ) {
yield obj[value];
}
}
const arr2 = Array.from(createInterator(obj2));
console.log(arr2); // ['name', 'age', 'sex', 'height'];