js高程及其面试题

    技术2022-07-10  139

    2020年出现的大厂面试题

    面试题1:作用域链

    var x = 1; function func(x, y = function anonymous1() {x = 2}) { x = 3; y(); console.log(x); // 1 } func(5); console.log(x); // 1

    1.函数func作用域内的变量是私有的,形参赋值x=5,私有赋值x=3,anonymous1函数的作用域链是func,所以函数y()执行会改变x=2,第一个console.log(x)打印2 2.全局作用域,第二个打印数值 x=1

    面试题2:作用域

    var x = 1; function func(x, y = function anonymous1() {x = 2}) { var x = 3; y(); console.log(x); //3 } func(5); console.log(x);//1 /* es6中存在块级作用域(只要{}[除对象之外的大括号] 出现let/const/function) 有一种情况也会产生 1.函数有形参赋值了默认值 2.函数体中有单独声明过某个变量 这样在函数运行的时候会产生两个上下文 第一个:函数执行形成的私有上下文EC(FUNC) => 作用域链/形参赋值/... 第二个:函数大括号包起来的就是块级上下文EC(BLOCK) */ /* *EC(G) *x=1 *func = AAAFFF000 */ var x = 1; function func(x, y = function anonymous1() {x = 2}) { /* *EC(FUNC)私有上下文 * 作用域链:<EC(FUNC),EC(G)> * x=5 * y=anonymous1 [[scope]]:EC(FUNC) *EC(BLOCK)块级上下文(上级上下文 EC(FUNC)) * 变量提升 var x * 在代码没有执行之前,我们会把EC(FUNC)中的值也给它一份 x=5 */ var x = 3; // 块级上下文中的x x=3 y(); // 不是块级的y,向上级找 EC(FUNC) //anonymous1执行 // 私有上下文EC(AN) 作用域链:<EC(AN),EC(FUNC)> // x = 2 修改的是EC(FUNC)中的2 console.log(x); //3 块级上下文中的x,还是3 } func(5); console.log(x);//1 // 相应三道练习题 { function foo() {} foo = 1; // =>1 } console.log(foo); // 函数 //----------------------------------------- { function foo() {} foo = 1; function foo() {} // 1 } console.log(foo); // 1 // ----------------------------------------- { function foo() {} foo = 1; function foo() {} foo = 2; // 2 } console.log(foo); //1

    面试题三:函数柯里化

    函数柯里化:必报实现存储值,后期用的机制 已知结果,求函数

    let res = fn(1,2)(3) console.log(res) // 6 // 答案 function fn (...outerArgs){ return function anonymous(...innerArgs){ return outerArgs.concat(innerArgs).reduce((a,b)=> a+b) } } // 简化 let fn = (...outerArgs) => {(...innerArgs)=> outerArgs.concat(innerArgs).reduce((a,b)=> a+b)}

    面试题4:函数式编程

    函数式编程

    /* 在函数式编程当中有一个很重要的概念就是函数组合, 实际上就是把处理数据的函数像管道一样连接起来, 然后让数据穿过管道得到最终的结果。 例如: const add1 = (x) => x + 1; const mul3 = (x) => x * 3; const div2 = (x) => x / 2; div2(mul3(add1(add1(0)))); //=>3 ​ 而这样的写法可读性明显太差了,我们可以构建一个compose函数,它接受任意多个函数作为参数(这些函数都只接受一个参数),然后compose返回的也是一个函数,达到以下的效果: const operate = compose(div2, mul3, add1, add1) operate(0) //=>相当于div2(mul3(add1(add1(0)))) operate(2) //=>相当于div2(mul3(add1(add1(2)))) ​ 简而言之:compose可以把类似于f(g(h(x)))这种写法简化成compose(f, g, h)(x),请你完成 compose函数的编写 */ const add1 = (x) => x + 1; const mul3 = (x) => x * 3; const div2 = (x) => x / 2; function compose(...funcs){ return function anonymous(...args){ if (funcs.length === 0) return args if (funcs.length === 1) return funcs[0](...args) let n = 0 return funcs.reduce((a,b)=>{ n++ if (n === 1) { // 第一次a是一个函数 return b(a(...args)) } return b(a) // 第二次开始,a是一个累加值 }) } } // 不传函数 let result = compose()(0,1) console.log(result) // 返回传进去的参数 // 传一个函数 let result = compose(add1)(0,1) console.log(result) // 返回第一个函数执行 // 传多个函数 let result = compose(add1,mul3,div2,add1)(0,1) console.log(result) // 依次执行,返回最后一个函数结束后的结果

    面试题5:原型链

    function Dog(name) { this.name = name; } Dog.prototype.bark = function () { console.log('wangwang'); } Dog.prototype.sayName = function () { console.log('my name is ' + this.name); } function _new() { //=>完成你的代码 } let sanmao = _new(Dog, '三毛'); sanmao.bark(); //=>"wangwang" sanmao.sayName(); //=>"my name is 三毛" console.log(sanmao instanceof Dog); //=>true // 答案 function _new(Func, ...args) { // 创建实例对象 let obj = {} obj.__proto__ = Func.prototype // IE let obj = Object.create(Func.prototype) // 方法执行,让里面的this指向实例对象 let result = Func.call(obj, ...args) // 分析返回结果 if (result !== null && (/^(object|function)$/.test(typeof result))) { return result } return obj }

    面试题6:重写call 方法

    ~function(){ function change(){ //=>实现你的代码 }; Function.prototype.change=change; }(); let obj = {name:'Alibaba'}; function func(x,y){ this.total=x+y; return this; } let res = func.change(obj,100,200); // let res = func.call(obj,100,200); 一样的效果 //res => {name:'Alibaba',total:300} // 答案 /* obj.xxx = func obj.xxx(10,20) // func执行,方法中的this指向obj */ ~function(){ function change(context, ...args){ // this -> func context = context == undefined ? window : context // 处理传值为空情况 let type = typeof context if(!/^(object|function)$/.test(type)){ // 处理传值为字符串情况 if (/^(symbol|bigint)$/.test(type)){ context = Object(context) }else{ context = new context.contructor(context) // 转换成对应的函数 } } let key = Symbol('key') console.log(key, this) context[key] = this // 指向 let result = context[key](...args) // 执行 delete context[key] return result }; Function.prototype.change=change; }();

    面试题7:重写bind方法

    ~function(){ //=>bind方法在IE6~8中不兼容,接下来我们自己基于原生JS实现这个方法 function bind(){ }; Function.prototype.bind=bind; }(); var obj = {name:'zhufeng'}; function func(){ console.log(this,arguments); //=>当点击BODY的时候,执行func方法,输出:obj [100,200,MouseEvent事件对象] } document.body.onclick = func.bind(obj,100,200); // 答案 /* bind执行完成后,返回的函数 document.body.onclick = function(ev){ func.call(obj, 100,200) } */ ~function(){ //=>bind方法在IE6~8中不兼容,接下来我们自己基于原生JS实现这个方法 function bind(context, ...args){ // this -> func let _this = this context = context == undefined ? window : context // 处理传值为空情况 let type = typeof context if(!/^(object|function)$/.test(type)){ // 处理传值为字符串情况 if (/^(symbol|bigint)$/.test(type)){ context = Object(context) }else{ context = new context.contructor(context) // 转换成对应的函数 } } return function anonymous(...innerArgs){ // _this指向func _this.call(context, ...args.concat(innerArgs)) } }; Function.prototype.bind=bind; }();

    PS:需配套视频讲解请发邮件到 songjierui5411@dingtalk.com 并备注文章标题

    Processed: 0.013, SQL: 9