【面试官】| 要不说说,JavaScript中的new操做符(别走)

文章第一时间发在笔者githubgit

什么是箭头函数

  • 语法简洁
  • 没有本身的this
  • 不能用做构造函数。
const agesArr = [12,13,7,8 ]

const res = agesArr.map(item=>`${item}岁`)
console.log(res) // [ '12岁', '13岁', '7岁', '8岁' ]
复制代码
const fn  = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
const res1 = fn()
console.log(res1) // 6
复制代码

优点

  • 关于函数的参数默认值面试

    • 以前
    function log(x, y) {
      y = y || 'World';
      console.log(x, y);
    }
    
    if (typeof y === 'undefined') {
      y = 'World';
    }
    复制代码
    • 如今
    function Point(x = 0, y = 0) {
      this.x = x;
      this.y = y;
    }
    复制代码
  • 写起来更短数组

  • 没有单独的this浏览器

  • 箭头函数使得表达更加简洁。bash

没有箭头函数

函数是根据如何被调用来定义这个函数的thisapp

  • 若是是该函数是一个构造函数,this指针指向一个新的对象
  • 在严格模式下的函数调用下,this指向undefined
function Person() {
        // Person() 构造函数定义 `this`做为它本身的实例.
        this.age = 0;

        setInterval(function growUp() {
          console.log(this);
          // 在非严格模式, growUp()函数定义 `this`做为全局对象,
          // 与在 Person()构造函数中定义的 `this`并不相同.
            // 此时的this是window 对象(浏览器环境)
          this.age++;
        }, 1000);
      }
复制代码

用箭头函数

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| 正确地指向 p 实例
  }, 1000);
}

var p = new Person();
复制代码

箭头函数不会建立本身的this,它只会从本身的做用域链的上一层继承this函数

普通函数与箭头函数有什么不一样

  • 函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象
let obj = {
  name: "张三",
  sayHi() {
    console.log(this); // obj 这个对象
    function sayName() { 
      console.log(this); // 是一个函数 this 指向window
    }
    sayName()
    const foo = ()=>{
      console.log(this) // obj 这个对象
    }
    foo()
  },
};
console.log(obj.name);
obj.sayHi();

复制代码
  • ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不须要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
// arguments变量的写法 相似数组的对象
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// rest参数的写法 真正的数组
const sortNumbers = (...numbers) => numbers.sort();
复制代码
  • 不可使用yield命令,所以箭头函数不能用做 Generator 函数。

面试题

根据new操做符相关的知识点通常会 延伸出如下的面试题 ,面试官你是否有不少问号测试

  • 问题一:new 以后都作了些什么??
  • 问题二:可否手写new操做符原理??

mdn关于new运算符关键字的描述

  1. 建立一个空的简单JavaScript对象(即{});
  2. 连接该对象(即设置该对象的构造函数)到另外一个对象 ;
  3. 将步骤1新建立的对象做为this的上下文 ;
  4. 若是该函数没有返回对象,则返回this

以上4条是MDN 上关于new 操做符(或者说关键字)的面试,简单的来体验下利用构造函数来new 一个对象

var self;

function Person(name) {
  console.log(this);
  self = this;
  this.name = name;
}
let p = new Person("张三");
console.log(p);
console.log(self === p); // true 构造函数中的this 绑定在了p这个对象上
console.log(p.__proto__ === Person.prototype); // 对象p的原型属性指向构造函数的原型,这样也就保证了实例可以访问在构造函数原型中定义的属性和方法。
复制代码

而后在构造函数添加原型方法

function Persion(name){
    this.name = name
}
console.log(Persion.prototype)
Persion.prototype.sayHello = function(){
    console.log(this) // 指向构造出的对象
    console.log(this.name) // 小明
}

let xiaoMing = new Persion('小明')
xiaoMing.sayHello()
复制代码

通过上文的简单案例咱们能够得知,

  • new 一个构造函数获得一个对象,它的原型属性(也就是__ proto __)与该构造函数的原型是全等

  • new 经过构造函数 Persion 建立出来的实例能够访问到构造函数中的属性,就行这样

    console.log(xiaoMing.name) // 小明
    复制代码
  • 言简意赅:new出来的实例对象经过原型链和构造函数联系起来

构造函数说白了也是一个函数,那是函数就能够有返回值

function Person(name) {
  this.name = name;
  // return 1; // 返回内部新建立的对象
  // return "1"; // 返回内部新建立的对象
  // return null; // 返回内部新建立的对象
  // return undefined; // 返回内部新建立的对象
  // return {}; // {} // 直接返回
  return function () {}; // 直接返回
  return [1]; // [1] // 直接返回
}
let p = new Person("李四");
console.log(p);
复制代码

有了给构造函数返回一个值得想法,那就经过不一样的数据类型 进行测试得出结论

  • 不一样的数据类型返回的效果是不同的,像数字1 字符串”1“ ,返回的依然是内部建立的对象
  • 那若是返回一个对象({})或者说数组(【】) 都会直接返回回去

小结

也就是说,构造函数通常不须要return

  • 返回通常的数据类型吧,不起做用
  • 返回对象吧, new 的意义又何在呢

手写一个本身的myNew

若是本身实现一个new 的话,首先要知足它的几点效果

  1. 一个构造函数会返回一个对象,那函数里就应该有对象

    let obj ={}
    复制代码
  2. 并将其__proto__属性指向构造函数的prototype属性

    obj.__proto__ = constructor.prototype;
    复制代码
  3. 调用构造函数,绑定this

    constructor.apply(obj, args)
    复制代码
  4. 返回原始值须要忽略,返回对象须要正常处理

    res instanceof Object ? res : obj
    复制代码

测试成果

function myNew() {
  let [constructor, ...args] = [...arguments];
  let obj = {};
  obj.__proto__ = constructor.prototype;

  let res = constructor.apply(obj, args);
  return res instanceof Object ? res : obj;
}

function Person(name) {
  this.name = name;
//   return {};
}

Person.prototype.sayHi = function () {
  console.log(`原型方法中的函数--${this.name}`);
};
let p1 = myNew(Person, "测试");
// console.log(p1)
p1.sayHi();
console.log(p1.name);
复制代码

箭头函数使用new

var Foo = () => {};
      var foo = new Foo(); // TypeError: Foo is not a constructor
复制代码
  • 不能够看成构造函数,也就是说,不可使用new命令,不然会抛出一个错误

this指向的固定化,并非由于箭头函数内部有绑定this的机制,实际缘由是箭头函数根本没有本身的this,致使内部的this就是外层代码块的this。正是由于它没有this,因此也就不能用做构造函数。

相关文章
相关标签/搜索