模范爸爸|「干货满满」1.5w字初中级前端面试复习总结( 三 )


使用:
function Person() {this.name = 'people'}Person.prototype.sayName = function () { console.log(this.name) }function Child() {this.name = 'child'}inherit(Child, Person)Child.prototype.age = 18let child = new Child()ES6 Classclass Person {constructor() {this.name = 'people'}sayName() {console.log(this.name)}}class Child extends Person {constructor() {super()this.name = 'child'}}Child.prototype.age = 18let child = new Child()Class 可以通过 extends 关键字实现继承 , 这比 ES5 的通过修改原型链实现继承 , 要清晰和方便很多 。
基本包装类型let str = 'hello'str.split('')基本类型按道理说是没有属性和方法 , 但是在实际操作时 , 我们却能从基本类型调用方法 , 就像一个字符串能调用 split 方法 。
为了方便操作基本类型值 , 每当读取一个基本类型值的时候 , 后台会创建一个对应的基本包装类型的对象 , 从而让我们能够调用方法来操作这些数据 。 大概过程如下:

  1. 创建String类型的实例
  2. 在实例上调用指定的方法
  3. 销毁这个实例
let str = new String('hello')str.split('')str = nullthisthis是函数被调用时发生的绑定 , 它指向什么完全取决于函数在哪里被调用 。 我理解的this是函数的调用者对象 , 当在函数内使用this , 可以访问到调用者对象上的属性和方法 。
this绑定的四种情况:
  1. new 绑定 。 new实例化
  2. 显示绑定 。 call、apply、bind手动更改指向
  3. 隐式绑定 。 由上下文对象调用 , 如 obj.fn() , this 指向 obj
  4. 默认绑定 。 默认绑定全局对象 , 在严格模式下会绑定到undefined
优先级new绑定最高 , 最后到默认绑定 。
new的过程
  1. 创建一个空对象
  2. 设置原型 , 将对象的 __proto__ 指向构造函数的 prototype
  3. 构造函数中的 this 执行对象 , 并执行构造函数 , 为空对象添加属性和方法
  4. 返回实例对象
注意点:构造函数内出现return , 如果返回基本类型 , 则提前结束构造过程 , 返回实例对象;如果返回引用类型 , 则返回该引用类型 。
// 返回基本类型function Foo(){this.name = 'Joe'return 123this.age = 20}new Foo() // Foo {name: "Joe"}// 返回引用类型function Foo(){this.name = 'Joe'return [123]this.age = 20}new Foo() // [123]call、apply、bind三者作用都是改变this指向的 。
call 和 apply 改变 this 指向并调用函数 , 它们两者区别就是传参形式不同 , 前者的参数是逐个传入 , 后者传入数组类型的参数列表 。
bind 改变 this 并返回一个函数引用 , bind 多次调用是无效的 , 它改变的 this 指向只会以第一次调用为准 。
手写callFunction.prototype.mycall = function () {if(typeof this !== 'function'){throw 'caller must be a function'}let othis = arguments[0] || windowothis._fn = thislet arg = [...arguments].slice(1)let res = othis._fn(...arg)Reflect.deleteProperty(othis, '_fn') //删除_fn属性return res}apply 实现同理 , 修改传参形式即可
手写bindFunction.prototype.mybind = function (oThis) {if(typeof this != 'function'){throw 'caller must be a function'}let fThis = this//Array.prototype.slice.call 将类数组转为数组let arg = Array.prototype.slice.call(arguments,1)let NOP = function(){}let fBound = function(){let arg_ = Array.prototype.slice.call(arguments)// new 绑定等级高于显式绑定// 作为构造函数调用时 , 保留指向不做修改// 使用 instanceof 判断是否为构造函数调用return fThis.apply(this instanceof fBound ? this : oThis, arg.concat(arg_))}// 维护原型if(this.prototype){NOP.prototype = this.prototypefBound.prototype = new NOP()}return fBound}