js高程及其面试题

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

js高程及其面试题_第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)私有上下文
	*	作用域链:
	*	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) 作用域链:
    // 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:需配套视频讲解请发邮件到 [email protected] 并备注文章标题

你可能感兴趣的:(js高级程序,javascript)