1.自我介绍。在项目里的角色。有遇到过什么困难吗?为什么选择前端。
2.登陆实现的原理。
3.了解浏览器渲染的不兼容吗?元素的样式不兼容。
不同浏览器的标签默认的margin和padding不同:使用Normalize来清除默认样式
块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大:在float的标签样式控制中加入 display:inline;将其转化为行内属性
4.CSS中class的优先级
css层叠规则:——《CSS权威指南》第三章 结构与层叠
- 显式权重:分为 !important, 来源两方面: !important读者样式 > !important创作人员样式 > 创作人员样式 > 读者样式 > 用户代理样式
- 特殊性:内联样式(1,0,0,0)> ID选择器(0,1,0,0) > 类选择器,属性选择器,伪类选择器(0,0,1,0) > 元素选择器,伪元素选择器(0,0,0,1) > 通配选择器(0,0,0,0)> 继承(null)
- 出现顺序:一个声明在样式表或文档中越后出现,他的权重就越大
.a{ color:red; } .b{ color:green; } <div class="a b"> ab </div> <div class="b a"> ba </div>
结果是什么颜色:两个都是绿色。因为:class的优先级与在元素中的指定顺序无关,和class的定义顺序有关,最后定义的优先级最高。
多类选择器: ——《CSS权威指南》第二章 选择器
<div class="a"> a </div> <div class="b"> b </div> <div class="a b"> ab </div> .a.b{ color:brown; } .a{ color:red; } .b{ color:green; }
5.函数变量提升+闭包
var count = 10; function a(){ console.log(count+10); } function b(){ var count = 20; return a(count) } b();
6.原型+原型链+构造
function foo(){ this.a = 1; return{ a:4, b:5} } let Foo = new foo(); Foo.prototype.a = 6; Foo.prototype.b = 7; Foo.prototype.c = 8; console.log(Foo.prototype.a); console.log(Foo.prototype.b); console.log(Foo.prototype.c);
new操作符具体做了什么,用代码解释:
var Foo = new foo();
该步一共做了三件事:即 var Foo = {}; //创建了一个空对象obj
Foo.__proto__ = foo.prototype; //将这个空对象的__proto__成员指向了foo函数对象prototype成员对象
foo.call(obj);//将Base函数对象的this指针替换成obj。
7.nodeJS异步+事件循环
setTimeout(function(){ console.log(2); },0); new Promise(function(resolve){ console.log(3); process.nextTick(resolve()); }).then(function(){ console.log(5); }); process.nextTick(function(){ console.log(7); }); setImmediate(function(){ console.log(1); },0);
输出:3 7 5 2 1
思路参考https://blog.csdn.net/weixin_45440502/article/details/109729016 7.判断nodejs异步输出顺序
8.斐波拉奇:f(0)=0,f(1)=1
暴力(递归):
var fib = function(n) { if (n<=0) return 0 if (n == 1) return 1 return fib(n-1)+fib(n-2) }
记忆(循环):
var fib = function(n) { if (n<=0) return 0 if (n == 1) return 1 let arr = [0,1]; let i =2; for(;i<=n;i++){ arr[i] = arr[i-1]+arr[i-2] } return arr[i-1] }
9.'get-element-by-id' 用驼峰法转化为 'getElementById'
数组:
用到字符串两个方法:charAt()和substr()。其他方法见我另一篇文章https://blog.csdn.net/weixin_45440502/article/details/109729016 第11点。
function combo(msg){ var arr=msg.split("-"); var i=1; for(;i<arr.length;i++){ arr[i]=arr[i].charAt(0).toUpperCase() + arr[i].substr(1,arr[i].length-1); } console.log(arr);//['get','Element','By','Id'] msg=arr.join(""); console.log(msg)//getElementById } combo("get-element-by-id");
或:用数组的方法:map()和slice()。数组其他方法见我另一篇文章 https://blog.csdn.net/weixin_45440502/article/details/109646845 第13点。
function getCamelCase( str ) { var arr = str.split( '-' ); return arr.map( function( item, index ) { if( index === 0 ){ return item; }else{ return item.charAt(0).toUpperCase() + item.slice( 1 ); } }).join(''); } console.log( getCamelCase( 'get-element-by-id' ) ); //getElementById
我当时写的方法:用到Array.from(arr)
function combo(msg){ var arr=msg.split("-"); var i=1; let temp,newarr; for(;i<arr.length;i++){ newarr = Array.from(arr[i]);//这里很重要,我当时写错了,写的是arr[i].from() newarr[0] = newarr[0].toUpperCase() arr[i] = newarr.join('') } console.log(arr);//['get','Element','By','Id'] msg=arr.join(""); console.log(msg)//getElementById } combo("get-element-by-id");
正则:
function getCamelCase( str ) { return str.replace( /-([a-z])/g, function( all, i ){ return i.toUpperCase(); } ) } console.log( getCamelCase( 'get-element-by-id' ) ); //getElementById
10.解释promise.all的作用,并写出原理
1、作用
- 入参是一个数组,可以传基本类型值,也可以传promise对象。
- 返回结果是一个Promise对象。
- 入参数组中的每一个都返回成功,才返回成功。
- 只要有一个执行失败,则返回失败。
2.适用场景
- 适合多个异步调用函数,并且多个异步函数的调用的入参和结果都无必然联系,比如多个文件的上传或下载。
- 多个异步函数的执行只关注成功或失败结果。
3.原理代码
Promise.all = function(values){ return new Promise((resolve,reject)=>{ let results = []; // 结果数组 let i = 0; let processData = (value,index)=>{ results[index] = value; // 当成功的个数 和 当前的参数个数相等就把结果抛出去 if(++i === values.length){ resolve(results); } } for(let i = 0 ; i< values.length;i++){ let current = values[i]; // 拿到数组中每一项 // 判断是不是一个promise if((typeof current === 'object' && current !==null)|| typeof current == 'function'){ // 如果是promise if(typeof current.then == 'function'){ // 就调用这个promise的then方法,把结果和索引对应上,如果任何一个失败了返回的proimise就是一个失败的promise current.then(y=>{ processData(y,i); },reject) }else{ processData(current,i); } }else{ processData(current,i); } } }); }
或
// 封装 Promise.all方法 Promise.all = function (values) { return new Promise((resolve, reject) => { let result = []; // 存放返回值 let counter = 0; // 计数器,用于判断异步完成 function processData(key, value) { result[key] = value; // 每成功一次计数器就会加1,直到所有都成功的时候会与values长度一致,则认定为都成功了,所以能避免异步问题 if (++counter === values.length) { resolve(result); } } // 遍历 数组中的每一项,判断传入的是否是promise for (let i = 0; i < values.length; i++) { let current = values[i]; // 如果是promise则调用获取data值,然后再处理data if (isPromise(current)) { current.then(data => { processData(i, data); }, reject); } else { // 如果不是promise,传入的是普通值,则直接返回 processData(i, current); } } }); }
4.代码解析
- Promise.all是挂载到Promise类实例上
- 返回的是一个Promise
- 需要遍历入参数组中的每一项,判断传入的是不是promise,如果是promise则执行then方法,然后将then方法中的成功回调的data返回,失败则reject
- 如果入参数组中有基本数值,则直接返回
- 通过计数器,来判断函数的执行结果
手写promise
源码:
// 上源码 ;(function (global) { global.Promise = Promise // 定义promise三种状态 const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' function Promise(fn) { this.state = PENDING this.fulfilledQueue = [] this.rejectedQueue = [] try { fn( // 此处需注意this指向 (res) => { this._resolve(res) }, (err) => { this._reject(err) } // 或者this.resolve.bind(this), this.reject.bind(this)) ) } catch (e) { reject(e) } } Promise.prototype = { constructor: Promise, _resolve: function (value) { if (value instanceof Promise) { return value.then( // 此处需注意this指向 (res) => { this._resolve(res) }, (err) => { this._reject(err) } ) } setTimeout(() => { if (this.state === PENDING) { this.state = FULFILLED this.value = value this.fulfilledQueue.forEach((fn) => fn(this.value)) } }) }, _reject: function (value) { setTimeout(() => { if (this.state === PENDING) { this.state = REJECTED this.value = value this.rejectedQueue.forEach((fn) => fn(this.value)) } }) }, then: function (fulfilled, rejected) { this.fulfilled = typeof fulfilled === 'function' ? fulfilled : (v) => v this.rejected = typeof rejected === 'function' ? rejected : (err) => { throw err } if (this.state === PENDING) { return new Promise((resolve, reject) => { this.fulfilledQueue.push(() => { try { this.value = this.fulfilled(this.value) resolve(this.value) } catch (error) { reject(error) } }) this.rejectedQueue.push(() => { try { this.value = this.rejected(this.value) resolve(this.value) } catch (error) { reject(error) } }) }) } if (this.state === FULFILLED) { return new Promise((resolve, reject) => { setTimeout(() => { try { this.value = this.fulfilled(this.value) resolve(this.value) } catch (error) { reject(error) } }) }) } if (this.state === REJECTED) { return new Promise((resolve, reject) => { setTimeout(() => { try { this.value = this.rejected(this.value) resolve(this.value) } catch (error) { reject(error) } }) }) } }, } })(window)