Js理解之路:Object.call与Object.create()实现继承的原理

122 篇文章 11 订阅

Function.prototype:call/apply/bind 是Function原型上的方法,这三个方法都是用来改变函数中的THIS的

call:[function].call([context],params1,params2,…)

(1)[function]作为Function内置类的一个实例,可以基于__proto__找到Function.prototype的call方法,并且把找到的call方法执行;

    (2) 在call方法执行的时候,会把[function]执行,并且把函数中的this指向为[context],并且把params1,params2…等参数值分别传递给函数

apply:[function].apply([context],[params1,params2,…])

和call作用一样,只不过传递给函数的参数需要一数组的形式传递给apply

 bind:[function].bind([context],params1,params2,…)

(1)语法上和call类似,但是作用和call/apply都不太一样;

(2)call/apply都是把当前函数立即执行,并且改变函数中的this指向的,而bind是一个预处理的思想,

(3)基于bind只是预先把函数中的this指向[context],把params这些参数值预先存储起来,但是此时函数并没有被执行


2. 通过Object.create(null)创建的对象是非常纯净的,原型链的属性和方法都不会携带。这就非常适合数组对象开发的时候,从对象中取值,提高循环效率。

var  obj  = Object.create(null) ;  
console.log(obj);   // 打印可以发现,obj 没有__proto__ 属性

3. 如果需要使用到对象的继承属性和方法,那就使用 obj = {}  或 obj = new Object() 这种方式

Object.create继承的应用

var A = function () { };
  A.prototype.sayName=function () {
    console.log('a');
  }
 
  // B的实例继承了A的属性
  var B = function () { };
  B.prototype = Object.create(A.prototype);
  var b = new B();
  b.sayName();  // a

划重点:相对于构造函数的继承Object.create继承实现了将A,B的原型完美分隔 。双方不会互相影响。这是Object.create亮点所在

Object.create()

作用:当没有构造函数的情况下,我们希望一个拿一个现有的对象作为一个模板,然后创建新的实例对象,我们就可以使用Object.create();其实就相当于复制一个对象。

举个例子,我们在使用过程中经常遇到,现在有一个对象A,A里面有属性和方法,我们现在需要一个和A有同样的属性和方法外,还另外新增一些属性,此刻我们就可以创建一个对象B,然后使用var B=Object.create(A);此时B就会继承A继承所有属性和方法,然后B还可以自己创建新的属性和方法。
官方解释:方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。创建实例对象。

构造函数作为模板,可以生成实例对象。但是,有时拿不到构造函数,只能拿到一个现有的对象。我们希望以这个现有的对象作为模板,生成新的实例对象,这时就可以使用Object.create()方法。

语法
Object.create(proto[, propertiesObject])
参数:
proto 新创建对象的原型对象。
[, propertiesObject]可选。如果没有指定为 undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。
返回值
一个新对象,带着指定的原型对象和属性。
实例

var person1 = {
  name: '张三',
  age: 38,
  greeting: function() {
    console.log('Hi! I\'m ' + this.name + '.');
  }
};

var person2 = Object.create(person1);

person2.name // 张三
person2.greeting() // Hi! I'm 张三.

上面代码中,对象person1是person2的模板,后者继承了前者的属性和方法

语法:
Object.create(proto[,propertiesObject])


参数

proto
创建对象的原型,表示要继承的对象


propertiesObject(可选 )
也是一个对象,用于对新创建的对象进行初始化

注:Object.create(null) 创建的对象是一个空对象,在该对象上没有继承 Object.prototype 原型链上的属性或者方法

我们来看看底层

Object.create =  function (o) {
    var F = function () {};
    F.prototype = o;
    return new F();
  };

F.prototype属性,进行了重新赋值,且指向传递的参数o;

应 用
示例代码:

//创建一个Obj对象
  var Obj ={
    name:'mini',
    age:3,
    show:function () {
      console.log(this.name +" is " +this.age);
    }
  }
  //MyObj 继承obj, prototype指向Obj
  var MyObj = Object.create(Obj,{
    like:{
      value:"fish",        // 初始化赋值
      writable:true,       // 是否是可改写的
      configurable:true,   // 是否能够删除,是否能够被修改
      enumerable:true      //是否可以用for in 进行枚举
    },
    hate:{
      configurable:true,
      get:function () { console.log(111);  return "mouse" }, 
      // get对象hate属性时触发的方法
      set:function (value) {                                 
      // set对象hate属性时触发的方法 
        console.log(value,2222);
        return value;
      }    
    }
  });

能想到MyObj 的输出结果是什么嘛?会有哪些属性?(先思考一下 )

看看运行结果,是否和你想的一样呢? 

 

你会发现,第一个参数,在返回对象的原型上,而不是直接属性,可再回顾一下Object.create实现的底层原理;

第二参数,则是对返回对象添加属性,且进行属性描述对象的设置,关于属性描述对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值