js 面试题搜罗, 一些代码段

js 面试题搜罗

ES6

///////////////////////////////
// from page-82
  // try-p82-keys
  var obj ={
    a:1,
    b:2,
  };
  Object.setPrototypeOf(obj,{
    c:3,
  });

  console.log(Object.keys(obj)); // ["a", "b"]
  console.log(JSON.stringify(obj)); // {"a":1,"b":2}

  var keys1 =[];
  for(let key in obj)keys1.push(key);
  console.log(keys1); // ["a", "b", "c"]

  var keys2 =[];
  for(let key in Object.assign({},obj))keys2.push(key);
  console.log(keys2); // ["a", "b"]
///////////////////////////////

逻辑

///////////////////////////////
  // 逻辑 a=1 b=2 不使用第三个变了量交换a,b
  
  // var a = 1, b = 2;
  // // 最牛逼的
  // a = [b,b=a][0] 

  // 0使用临时变量 - low
  // var t = a
  // a = b
  // b = t
  
  // 1
  // a = a + b
  // b = a - b
  // a = a - b
  
  // 2-1
  // a = a^b //a^=b
  // b = b^a //b^=a
  // a = a^b //a^=b
  
  // 2-2
  // a = (b^=a^=b)^a;

  // 3
  // a = {a: b,b: a}
  // b = a.b
  // a = a.a
  
  // 4 
  // a = [a,b]
  // b = a[0]
  // a = a[1]
  
  // 5 ES6 解构赋值
  // [a,b] = [b,a] 

  // console.log('ab值互换', a, b)
///////////////////////////////

变量提升

///////////////////////////////
  // 变量提升 函数优先级高于变量
  function blts(){
    console.log(a);// undefined
    var a = 2;
  }
  blts();

  function fn(a){
    console.log(a); // a(){}
    var a = 2;
    function a(){}
    console.log(a); // 2
  }
  fn(1)

  var time = function(){
    console.log(1);
    return 1
  }
  function time(){
    console.log(2)
    return 2
  }
  console.log('构造函数: ', time()); // var time 1; => 构造函数:  1
///////////////////////////////
///////////////////////////////
  // 变量提升 + 原型链
  function Foo(){
    getName = function(){ console.log(1) }
    return this
  }
  Foo.getName = function(){ console.log(2) }
  Foo.prototype.getName = function(){ console.log(3) }
  var getName = function(){ console.log(4) }
  function getName(){ console.log(5) }
  
  // 请写出以下输出结果
  Foo.getName(); // 2
  getName(); // 4
  Foo().getName(); // 1
  getName(); // 1
  new Foo.getName(); // 2
  new Foo().getName(); // 3
  new new Foo().getName(); //3
///////////////////////////////
///////////////////////////////
  // 
  var a = {n: 1};
  var b = a;
  a.x = a = {n: 2};
  console.log(a.x); // undefined
  console.log(b.x); // {n: 2}
///////////////////////////////
///////////////////////////////
  // 
  function test(person) {
    person.age = 26
    person = {
      name: 'yyy',
      age: 30
    }
    return person
  }
  var p1 = {
    name: 'yck',
    age: 25
  }
  const p2 = test(p1)
  console.log(p1) // {age: 26, name: "yck"}
  console.log(p2) // {age: 30, name: 'yyy'}
///////////////////////////////
///////////////////////////////
  // 
  var foo = {
    bar: function(){
      let barr = 'barr'
      console.log(barr, this.barr)
      return this.baz;
    },
    baz: 1
  };
  (function(){
    arguments.barr = 'arguments-barr'
    arguments.baz = 'arguments-baz'
    // console.log(this) // window
    // console.log(arguments) // Arguments {}
    console.log(arguments[0]) // 匿名函数: f(){let barr...}
    console.log(typeof arguments[0]()); // undefined
  })(foo.bar)
  // 这里 this 指向 arguments , arguments 调用的
  
///////////////////////////////
///////////////////////////////
  // 
  console.log( '{} + [] //', {} + []); // [object Object]
  console.log( '[] + {} //', [] + {}); // [object Object]
  console.log( '{} + [] == 0', {} + [] == 0 ); // false
  console.log( '{a:1} + [] == 0', {a:'1'} + [] == 0 ); // false
  console.log( '[] + {} == 0', [] + {} == 0 ); // false
///////////////////////////////
///////////////////////////////
  // 1
  console.log(a);
  var a = 12;
  function fn(){
    console.log(a);
    var a = 13;
  }
  fn();
  console.log(a);
  // undefined undefined 12
  ///////////////////////////////

  // 2
  console.log(a);
  var a = 12;
  function fn(){
    console.log(a);
    a = 13;
  }
  fn();
  console.log(a);
  // undefined 12 13

  // 3
  console.log(a);
  a = 12;
  function fn(){
    console.log(a);
    a = 13;
  }
  fn();
  console.log(a);
  // 报错 a is not defined

  // 4
  /**
   * 变量提升
   *  var foo;
   *  bar = aaafff000;
   */
  var foo = 1;
  function bar(){
    /**
     * 形参赋值: 无
     * 变量提升
     *  var foo; (不管条件是否成立, 都要进行变量提升, 新浏览器中对于判断体中的函数只是提前声明)
     */
    if(!foo){ // => !undefined => true
      var foo = 10;
    }
    console.log(foo); // => 10
  }
  bar(); // 10

  // 5 变量/函数 声明提升, 闭包 保存/保护 作用
  var n = 0;
  function a(){
    var n = 10;
    function b(){
      n++;
      console.log(n); // => 11
    }
    b();// => 12
    return b;
  }
  var c = a();
  c();
  console.log(n); // => 0

  // 6 
  var a = 10, b = 11, c = 12;
  function test(a){
    a = 1;
    var b = 2;
    c = 3;
  }
  test(10);
  console.log(a) // 10
  console.log(b) // 11
  console.log(c) // 3

  // 7 不管条件是否成立, 都要进行变量提升
  if(!('a' in window)) {
    var a = 1;
  }
  console.log(a); // undefined

  // 8 arguments 累数组对象{x, y, a}
  // 变量提升
  // var a;
  // b = aaafff000;
  var a = 4;
  function b(x, y, a) {
    // 形参赋值: x=1 y=2 a=3
    // 变量提升
    //=> arguments: 函数内置的实参集合, 不管是否设置形参,传递的实参值在这个集合都存在
    // arguments: {0: 1, 1: 2, 2: 3, length: 3, callee: 函数本身b(){}...}
    // 在js非严格模式下, 函数中的形参变量和arguments存在映射机制(映射: 相互之间影响)
    // 第一个形参变量值修改为100,那么ARG[0]的值也跟着修改为100;
    // ARG[1]的值修改为200, 那么第二个形参变量Y的值也会跟着变为200...
    console.log(a); // 3
    arguments[2] = 10; //=>把传递的第三个实参值修改为10, 此时第三个形参变量a也会受到影响
    console.log(a); // 10
  }
  a = b(1,2,3);
  console.log(a); // undefined

  // 8-1 arguments 形参 映射机制(非严格模式)
  function fn(x,y) {
    // 形参
    //    x = 10
    //    y = undefined
    // ARG
    //  0: 10
    //  length: 1
    /// ARG和形参之间的映射是以ARG的索引为基础完成的,
    /// ARG中有这个索引, 浏览器会完成对应形参变量中的映射机制搭建,
    /// 如果形参比ARG中个数多, 那么多出的形参是无法和ARG中对应的索引建立关联的
    var arg = arguments;
    arg[0] = 100;
    console.log(x); // 100
    y = 200;
    console.log(arg[1]); // undefined

    arg[1] = 300;
    console.log(y); // 200
    //=> arguments和形参的映射机制建立函数执行后形参赋值的一瞬间, 此时能建立映射机制的建立映射机制, 不能建立起来的, 以后不管怎么操作都无法建立了
  }
  fn(10);

  // 8-2 JS 严格模式
  // => 在当前作用域的第一行 添加 'use strict' 即可, 这样在当前作用域中就开启了js的严格模式

  /*-- use [TAB] --*/
  //'use strict'; //=> 整个js都开启了严格模式(只对当前文件的代码生效, 下一个JS文件需要开启严格模式, 第一行还需要在编写)
  // 真实项目中, 把所有 JS 文件合并压缩为一个导入到页面中
  // 故使用闭包 防止严格模式失效
  ~function(){
    'use strict';
    // ...自己的代码
  }();
  ~function(){
    // ...别人的代码
  }();

  // 8-3 JS 严格模式和非严格模式 区别
  //=> 1. 严格模式下 arguments.callee/ arguments.callee.caller 不能使用(报错 在严格模式下不能使用)
  //=> 2. 在严格模式下 ARGUMENTS和形参没有映射机制
  //=> 3. 在严格模式下不允许给一个对象设置重复属性名的: "obj={n:1,n:2}"
  //=> 4. 在严格模式下, 函数执行, 如果没有明确指定执行的主体(函数前面没有点.), 不再像非严格模式下一样, 都统一交给window, 而是让this 指向undefined, 代表没有执行主体
  function fn(){console.log(this)} fn(); // window(非严格模式) undefined(严格模式)
  // =>高程三, 最后有严格模式和非严格模式汇总

  var color = 'red';
  delete color; //严格模式不允许对变量调用delete操作符; 非严格模式可以, 但是会静默失败(返回false);严格模式下删除变量也会导致错误.

  console.log(color)
///////////////////////////////
///////////////////////////////
  //费波拉希数列
  function fib(n) {
    return function(n, a, b) {
      return n > 0 ? arguments.callee(n - 1, b, a + b) : a;
    } (n, 0, 1);
  }
  // console.log(fib(0)); //0
  // console.log(fib(1)); //1
  // console.log(fib(2)); //1
  // console.log(fib(3)); //2
  // console.log(fib(4)); //3
  // ......
  // console.log(fib(50)); //12586269025
  // console.log(fib(51)); //20365011074,这里是上到第50个阶梯
  let fibn = fib(10);
  console.log(fibn); // 55

  function generateFibonaccis(n){
    var fib = [1, 1]
    for( var i = 2; i < n; i++){
      fib[i] = fib[i-2] + fib[i-1]
    }
    return fib
  }
  let fibonaccis = generateFibonaccis(10);
  console.log(fibonaccis.join(' ')); // 1 1 2 3 5 8 13 21 34 55
///////////////////////////////

Array 数组

///////////////////////////////
  /** 第 30 题:数组合并: 请把俩个数组 
   *  [A1, A2, B1, B2, C1, C2, D1, D2] 和 [A, B, C, D],
   *  合并为 [A1, A2, A, B1, B2, B, C1, C2, C, D1, D2, D]
   */
  let arr1 = ['A1','A2','B1','B2','C1','C2','D1','D2']
  let arr2 = ['A','B','C','C'].map( item =>{
    return item + 3
  })
  let arr3 = [...arr1, ...arr2] .sort().map((item) => {
    if(item.includes('3')){
      return item.split('')[0]
    }
    return item
  })
  console.log(arr3); // ["A1", "A2", "A", "B1", "B2", "B", "C1", "C2", "C", "C", "D1", "D2"]
///////////////////////////////
///////////////////////////////
  /** 数组给定一个整数数组 nums 和一个目标值 target,
   *  请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
   *  你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
   * 
   *  示例:
   *  给定 nums = [2, 7, 11, 15], target = 9
   *  因为 nums[0] + nums[1] = 2 + 7 = 9
   *  所以返回 [0, 1]
   */

  var twoSum = function (nums, target) {
    const map = {};
    const len = nums.length;
    for (let i = 0; i < len; i++) {
      const res = target - nums[i];
      if (map[res] || map[res] === 0) {
        return [map[res], i]
      }
      map[nums[i]] = i;
    }
  };
  console.log(twoSum([4,1,3,2],3)) // [1, 3]
///////////////////////////////

ES6

///////////////////////////////
  // const
  var CONST = {};
  Object.defineProperty(CONST, 'a', {
    value: 2,
    writable: false,
    configurable: false,
    enumerable: true,//可枚举
  })
  console.log('CONST.a = ', CONST.a);
  CONST.a = 3;
  console.log('改变了没? CONST.a = ',CONST.a); // 2 相当于ES6的const 定义的常量不可改变
///////////////////////////////
///////////////////////////////
  // a == 1 && a == 2 && a == 3 值为 true  how to ?

  // const a = {
  //   value: 0
  // }
  // a.valueOf = function () {
  //   return this.value += 1
  // }
  let a = {
    value: 0,
    valueOf(){
      return ++this.value
    }
  }
  
  // var a = [1, 2, 3]
  // a.join = function(){ return this.shift() }

  // var a = {
  //   value: 0
  // }
  // a.vauleOf = function(){
  //   return this.value += 1
  // }

  console.log('a == 1 && a == 2 && a == 3', a == 1 && a == 2 && a == 3) // true

  // a === 1 && a === 2 && a === 3; // true ?
  // var value = 0 //window.value
  // Object.defineProperty(window, 'a', {
  //   get: function(){
  //     return this.value += 1
  //   }
  // })
  // console.log('a === 1 && a === 2 && a === 3', a === 1 && a === 2 && a === 3) // true

  
///////////////////////////////

闭包

///////////////////////////////
/**
1.闭包的概念:

    闭包就是一个函数,两个函数彼此嵌套,内部函数就是闭包形成闭包条件是内部函数需要通过return给返回出来。

    看下面的代码,你就懂了:

    function f1(){
        function f2(){
            alert("我是js闭包!");
        }
        return f2;
    }
    var f=f1();
    f();  //弹出:我是js闭包!

2. 闭包特点
    闭包有权利调用其上级环境的变量信息。父级环境的信息已经固化为本身AO的成员了。

    看下代码,更好理解:

    function f1(){
      var bb = "闭包";
      function f2(){
        alert('我是'+bb);
      }
      return f2;
    }
    var f = f1();
    f();  //弹出:我是js闭包

3. 闭包使用规则

同一个闭包机制可以创建多个闭包函数出来,它们彼此没有联系,都是独立的。

并且每个闭包函数可以保存自己个性化的信息。

看下代码,理解下三个闭包彼此独立、没有联系:

    function f1(num){
      function f2(){
        alert('数字:'+num);
      }
      return f2;
    }
    var fa = f1(10);
    var fb = f1(20);
    var fc = f1(30);
    fa();   //数字:10
    fb();   //数字:20
    fc();   //数字:30
    
4. 闭包的使用例子,加深理解闭包
    //创建数组元素
    var num = new Array();
    for(var i=0; i<4; i++){
        //num[i] = 闭包;//闭包被调用了4次,就会生成4个独立的函数
        //每个函数内部有自己可以访问的个性化(差异)的信息
        num[i] = f1(i);
    }
    function f1(n){
        function f2(){
            alert(n);
        }
        return f2;
    }
    num[2]();  //2
    num[1]();  //1
    num[0]();  //0
    num[3]();  //3
  */

  function foo() {
    var i = 1;
    return function() {
      i++;
      console.log(i);
    }
  }
  var aFn = foo(), bFn = foo();
  aFn(); // 2
  aFn(); // 3
  bFn(); // 2

  //--------------------------------------------------->

  function funca(){
    y = function(){
      X=2;
    };
    return function(){
      var x=3;
      y();
      console.log(this.x); // 3
    }.apply(this, arguments);
  }
  funca();//undefined

  //--------------------------------------------------->

  /**
   * 闭包 函数自执行 this指向
   */
  var func = (function (a) {
    this.a = a
    return function (a) {
      a += this.a
      return a
    }
  })(function (a, b) {
    return a
  }(1, 2))
  console.log('闭包多层嵌套: ', func(5)) // 6
  // 理解过程
  var func = (function (a) {
    this.a = a
    return function (a) {
      a += this.a
      return a
    }
  })(1)
  var func = function (a = 1) {
    this.a = 1
    return function (a) {
      a += 1
      return a
    }
  }
  // 即 func 自执行函数返回一个函数 function(a){ return a += 1 } 这个函数将传递的参数加 1 返回
  funcc = function (a) {
    return a += 1
  }
  console.log('分析后的func为一个函数', funcc(4)); // 5
  
///////////////////////////////

[‘1’, ‘2’, ‘3’].map(parseInt)

parseInt(param, radix) 相当于 parseInt(String(param).trim(), radix)

  // parseInt()
  const value = parseInt(string[, radix]);

其中 string是一个要解析的字符串,如果不是字符串,则使用toString()方法给转换成string,开头的空格会被忽略。

radix是一个介于2-36的整数。表示一个基数,要将字符串转换成这个基数的进制。默认是10。

返回值是一个整数或者NaN。

  // map() 创建新数组, 结果是遍历的数组每个元素执行提供的函数返回的结果.
  const new_array = arr.map(function callback(currentValue[,index[, array]]) {
    // Return element for new_array
  }[, thisArg])
  ['1', '2', '3'].map(parseInt) 

这意味着,每个map的迭代,都要给parseInt传递两个参数,item和index,就是字符串和基数。

那这个表达式可以写成

  ['1', '2', '3'].map((item, index) => parseInt(item, index))

返回的结果应该是:

  parseInt('1', 0) // 1 
  parseInt('2', 1) // NaN
  parseInt('3', 2) // NaN 因为3不是2进制里的数,所以就报错。

所以该表达式返回的数组为:

['1', '2', '3'].map(parseInt) // [1, NaN, NaN]

加里·伯恩哈德例子也就很好解释了,这里不再赘述

['10','10','10','10','10'].map(parseInt); // [10, NaN, 2, 3, 4]

///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////
///////////////////////////////
  // 
  
///////////////////////////////