实现new方法

new可以用来构造一个实例,有以下步骤

  • 创建一个新对象
  • 新对象的原型proto指向构造函数的原型
  • 执行构造函数
  • 判断构造函数返回值是否是对象或者函数,如果是返回返回值,如果不是,返回这个新对象

    1. function New(constructor) {
    2. const object = constructor.prototype === null ? {} : Object.create(constructor.prototype);
    3. let res = null;
    4. if (typeof constructor === 'function') {
    5. res = constructor.apply(object, Array.prototype.slice.call(arguments, 1));
    6. }
    7. if (res !== null && (typeof res === 'object' || typeof res === 'function')) {
    8. return res;
    9. }
    10. return object;
    11. }

    对象字面量{}与Object.create(null)区别:

  • 对象字面量与new Object()是一样的,都有Object.prototype的原型,可以正常使用对象的属性

  • Object.create(null)是创建一个原型为null的对象,没有原型链

区分使用new调用构造函数还是普通调用

  • 构造函数中this指向,new调用时this指向实例,普通调用this指向window或undefined

    1. function Person() {
    2. if (this instanceof Person){
    3. // new调用
    4. }
    5. }
  • 通过constructor,new调用时constructor指向构造函数,普通调用时,constructor指向Object

    1. function Person() {
    2. if (this.constructor === Person){
    3. // new调用
    4. }
    5. }
  • 通过new.target,new调用时new.target指向构造函数,普通调用时指向undefined

    1. function Person() {
    2. if (new.target === Person){
    3. // new调用
    4. }
    5. }

    实现Object.create

    Object.create主要就是创建一个以传参作为原型的对象

    1. function create(proto, propertyObject) {
    2. const F = function () { };
    3. F.prototype = proto;
    4. const obj = new F();
    5. if (propertyObject) {
    6. Object.defineProperties(obj, propertyObject)
    7. }
    8. return obj;
    9. }

    实现instanceOf

    instanceOf主要判断实例是否是某个构造函数的实例,只要该构造函数的原型在实例的原型链上,都会返回true

    1. function instanceOf(instance, constructor) {
    2. let proto = instance.__proto__;
    3. while (proto !== null) {
    4. if (proto === constructor.prototype) {
    5. return true;
    6. }
    7. proto = proto.__proto__;
    8. }
    9. return false;
    10. }

    实现call和apply

    call和apply都是改变this的指向并立即执行,区别在于传参的个数,实现原理就是把函数绑在context上后调用 ```javascript function call(context, …args) { if (!context || typeof context !== ‘object’) return; const key = new Symbol(); context[key] = this; const result = contextkey; delete context[key]; return result; }

function apply(context, args) { if (!context || typeof context !== ‘object’) return; const key = new Symbol(); context[key] = this; const result = contextkey; delete context[key]; return result; }

  1. <a name="Ahebs"></a>
  2. # 实现bind
  3. bind也是改变this的指向,不过不会立即执行,而是返回一个函数,bind功能如下
  4. - 改变原有this指向
  5. - 返回该函数的拷贝
  6. - 当使用new 调用绑定后的函数时,之前绑定的this无效,new操作符修改this的优先级更高
  7. ```javascript
  8. function bind(context) {
  9. if (!context || typeof context !== 'object') return;
  10. if (typeof this !== 'function') return;
  11. const self = this;
  12. const args = Array.prototype.slice.call(arguments, 1);
  13. const func = function () {
  14. self.apply((this instanceof self) ? this : context, args.concat(Array.prototype.slice.call(arguments)));
  15. }
  16. func.prototype = Object.create(this.prototype);
  17. return func;
  18. }