# 收集一些 javascript 相关的面试题

# 实现 sum(1,2,3)==sum(1)(2)(3)

function sum(...args) {
  function currySum(...rest) {
    args.push(...rest);
    return currySum;
  }
  currySum.toString = function() {
    return args.reduce((result, cur) => {
      return result + cur;
    });
  };
  currySum.toNumber = function() {
    return args.reduce((result, cur) => {
      return result + cur;
    });
  };
  return currySum;
}

const num = sum(1, 2, 3);
const num2 = sum(1)(2)(3);
console.log(`num`, num);
console.log(`num2`, num2);

# 不借助变量,交换两个数

# 1. 算术交换

针对的是 Number,或者类型可以转换成数字的变量类型

function swap(a, b) {
  a = a + b;
  b = a - b;
  a = a - b;
}

通过算术运算过程中的技巧,可以巧妙地将两个值进行互换。但是,有个缺点就是变量数据溢出。因为 JavaScript 能存储数字的精度范围是 -2^532^53。所以,加法运算,会存在溢出的问题。

# 2. 异或运算

^ 按位异或 若参加运算的两个二进制位值相同则为 0,否则为 1

此算法能够实现是由异或运算的特点决定的,通过异或运算能够使数据中的某些位翻转,其他位不变。这就意味着任意一个数与任意一个给定的值连续异或两次,值不变.

a = a ^ b;
b = a ^ b;
a = a ^ b;

# 3. ES6 的解构(真香~)

[a, b] = [b, a];

# 实现一个 new

# 方法一

function myNew() {
  // 1、创建一个空的对象
  const obj = new Object();
  // 2、获得构造函数,同时删除 arguments 中第一个参数
  const Cons = [].shift.call(arguments);
  // 3、链接到原型,obj 可以访问构造函数原型中的属性 obj.__proto__ -> Cons.prototype
  Object.setPrototypeOf(obj, Cons.prototype);
  // 4、绑定 this 实现继承,obj 可以访问到构造函数中的属性
  const res = Cons.apply(obj, arguments);
  // 5、优先返回构造函数返回的对象
  return res instanceof Object ? res : obj;
}

# 方法二

function myNew() {
  // 1、获得构造函数,同时删除 arguments 中第一个参数
  const cons = [].shift.call(arguments);
  // 2、创建一个空的对象并链接到原型,obj 可以访问构造函数原型中的属性
  const obj = Object.create(cons.prototype);
  // 3、绑定 this 实现继承,obj 可以访问到构造函数中的属性
  const res = cons.apply(obj, arguments);
  // 4、优先返回构造函数返回的对象
  return res instanceof obj ? res : obj;
}

# instanceof 原理及实现

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。

function C() {}
function D() {}

var o = new C();

o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype
o instanceof D; // false,因为 D.prototype 不在 o 的原型链上

instanceof 原理就是一层一层查找 proto,如果和 constructor.prototype 相等则返回 true,如果一直没有查找成功则返回 false。

instance.[__proto__...] === instance.constructor.prototype

知道了原理后我们来实现 instanceof,代码如下。

function myInstanceOf(L, R) {
  let proto = R.prototype,
    __pro = L.__proto__;
  while (true) {
    // Object.prototype.__proto__ === null
    // 如果是null说明已经达到原型链最顶端,就直接返回false
    if (__pro === null) return false;
    //  L.__proto__ === R.prototype 如果严格返回 那就是构造函数的原型(R.prototype)存在于实例的原型链上(L.__proto__)
    if (proto === __pro) return true;
    // 递归原型链向上查找
    __pro = __pro.__proto__;
  }
}

// 测试
function C() {}

function D() {}

var o = new C();
console.log(myInstanceOf(o, C)); // true
console.log(myInstanceOf(o, D)); // false

# 最后

文中若有不准确或错误的地方,欢迎指出,有兴趣可以的关注下Github,一起学习呀~~

Last Updated: 2020/9/7 下午8:45:37