一些常见面试题

递归实现阶乘

function factorial(a) {
    if (a == 1) {
        return 1;
    }
    return a * factorial(a - 1);
}
var res = factorial(3);
console.log(res);

实现 add(2)(3) add(2, 3) 都可以求出结果5的add函数()

function add(a, b) {
    if (b != undefined) {
        return a + b;
    }
    return function (c) {
        return a + c;
    }
}
console.log(add(2)(3));
console.log(add(2, 3));

提供数组[5, 2, 1, 38],获得结果字符串"53821"

var arr = [5, 1, 2, 38];
var str = arr.sort().reverse().join('')
console.log(str);
Array(2).join(); // ,
Array(3).join(); // ,,
Array(2, 3).join(); // 2,3
const a = (x) => x + 1;
const b = (x) => x * 2;
const c = (x) => x * x;

// const compose = (...fns) => (x) => fns.reduce((accumulate, fn) => fn(accumulate), x);

const compose = (...fns) => { // fns = [a, b, c]

    return (x) => { // x = 4

        return fns.reduce((accumulate, fn) => { // return 100
            // 4   x + 1
            // 5   x * 2
            // 10  x * x
            return fn(accumulate)
        }, x) // x = 4
    }
}

const composedFn = compose(a, b, c);
const result = composedFn(4);
console.log(result);

1~9随机组合,可以组成三位数,每个数字智能使用一次,例如a=198 b = 243 c=567,这样的组合有很多,请编程找出所有这些组中中,满足a=b*2,b=c*2。(只写程序,不必给出结果),并写出算法复杂度


  1. Promise与bind与箭头函数的问题?

    class Foo {
        constructor (name) {
            this.name = name
        }
        greet () {
            console.log('hello, this is ', this.name)
        }
        someThingAsync () {
            return Promise.resolve()
        }
        asyncGreet () {
            this.someThingAsync().then(this.greet)
    
            // bind绑定
            // this.someThingAsync().then(this.greet.bind(this))
    
            // 使用箭头函数
            // this.someThingAsync().then(() => this.greet())
        }
    }
    new Foo('dog').asyncGreet()
    
  2. 作用域问题

    var arr = [];
    for (var i = 0; i < 10; i++) {
        arr.push(function () {
            console.log(i);
        })
    }
    
    arr[0]();
    arr[1]();
    arr[2]();
    // 解决办法 let
    // 使用bind实现 console.log.bind(null, this)
    
  3. 排序算法:冒泡排序、快速排序

  4. 如何判断一个对象的类型

    Object.prototype.type = function () {
        // 使用Object原型上的方法,将对象转为字符串
        var res = Object.prototype.toString.call(this);
        // 从第8位开始截取,然后删除最后一位
        res = res.substring(8).slice(0, -1);
        // 返回结果
        return res;
    };
    
  5. 闭包的使用,构造函数内部变量私有化

const Person = function (name) {
    this.name = name;
    let gender = 'F';
    function genderFunc() {
        return gender;
    }
    this.gender = genderFunc();
}

var p = new Person('xiaoming');
console.log(p.gender);
  1. 使用new关键字构建对象的本质?
function Person(name) {
    this.name = name;
}
var p = new Person('xiaoming');
console.log(p);
// 代码解析
function Person(name) {
 // 1. 创建对象,并赋值给this
 this = {};
 // 2. 修改constructor
 this.constructor = Person;
 // 3. 设置属性
 this.name = name;
 // 4. 返回this
 return this;
}
  1. new关键字写与不写都可以构建对象,如何实现该构造函数?

    function Person(name, age) {
        // 判断this是否为当前的构造函数
        if (!(this instanceof Person)) {
            return new Person(name, age);
        }
        this.name = name;
        this.age = age;
    }
    
    var p1 = new Person('xiaoming', 19);
    var p2 = Person('xiaoming', 20);
    
    console.log('-------------');
    console.log(p1);
    console.log(p2);
    
  2. 写出结果:

    alert(1 && 2); // 
    alert(1 || 2); // 
    
  3. 写出结果:

    var obj = {
        a: 1,
        b: function () {
            console.log(this.a)
        }
    };
    
    var a = 2;
    var objb = obj.b;
    
    obj.b(); // 1
    objb(); // 2
    obj.b.call(window); // 2
    
  4. 写出结果:

    function A() {
    
    }
    function B(a) {
        this.a = a;
    }
    function C(a) {
        if (a) {
            this.a = a;
        }
    }
    
    A.prototype.a = 1;
    B.prototype.a = 1;
    C.prototype.a = 1;
    
    console.log(new A()); // 原型上面有a = 1
    console.log(new B()); // 自身和原型上都有a 自身 a = undefined  原型 a = 1
    console.log(new C(2)); // 自身和原型上都有a 自身 a = 2 原型 a = 1
    
  5. 写出结果:

    var a = 1;
    function b() {
        var a = 2;
        function c() {
            console.log(a);
        }
        return c;
    }
    
    b()(); // 2
    var res = b();
    res(); // 2
    

    闭包,内层函数持有外层函数的变量,即便在外部调用,也会使用内部的a

  6. 解释下作用域链?

    当执行一段JavaScript代码(全局代码或函数)时,JavaScript引擎会创建为其创建一个作用域又称为执行上下文(Execution Context),在页面加载后会首先创建一个全局的作用域,然后每执行一个函数,会建立一个对应的作用域,从而形成了一条作用域链。每个作用域都有一条对应的作用域链,链头是全局作用域,链尾是当前函数作用域。
    
    作用域链的作用是用于解析标识符,当函数被创建时(不是执行),会将this、arguments、命名参数和该函数中的所有局部变量添加到该当前作用域中,当JavaScript需要查找变量X的时候(这个过程称为变量解析),它首先会从作用域链中的链尾也就是当前作用域进行查找是否有X属性,如果没有找到就顺着作用域链继续查找,直到查找到链头,也就是全局作用域链,仍未找到该变量的话,就认为这段代码的作用域链上不存在x变量,并抛出一个引用错误(ReferenceError)的异常。
    
  7. AJAX并发问题?

    
    
  8. 解释下原型链?

    JavaScript中的每个对象都有一个prototype属性,我们称之为原型,而原型的值也是一个对象,因此它也有自己的原型,这样就串联起来了一条原型链,原型链的链头是object,它的prototype比较特殊,值为null。
    
    原型链的作用是用于对象继承,函数A的原型属性(prototype property)是一个对象,当这个函数被用作构造函数来创建实例时,该函数的原型属性将被作为原型赋值给所有对象实例,比如我们新建一个数组,数组的方法便从数组的原型上继承而来。
    
    当访问对象的一个属性时, 首先查找对象本身, 找到则返回; 若未找到, 则继续查找其原型对象的属性(如果还找不到实际上还会沿着原型链向上查找, 直至到根). 只要没有被覆盖的话, 对象原型的属性就能在所有的实例中找到,若整个原型链未找到则返回undefined;
    
  9. body中的onload()函数和jQuery中的document.ready()有什么区别?

    1、我们可以在页面中使用多个document.ready(),但只能使用一次onload()。
    2、document.ready()函数在页面DOM元素加载完以后就会被调用,而onload()函数则要在所有的关联资源(包括图像、音频)加载完毕后才会调用。
    
  10. 什么情况下会遇到内存泄露?如何解决?

    内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。
    
    setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏
    闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)
    

你可能感兴趣的:(一些常见面试题)