jQuery源码之extend的实现

更新日期: 2019-08-07阅读: 1.9k标签: 源码

extend是jquery中一个比较核心的代码,如果有查看jQuery的源码的话,就会发现jQuery在多处调用了extend方法。


作用

  1. 对任意对象进行扩展
  2. 扩展某个实例对象
  3. 对jquery本身的实例方法进行扩展


实现

基础版本, 对简单对象进行扩展

   jQuery.prototype.extend = jQuery.extend = function(){
     var target = arguments[0] || {}; //获取第一个参数作为目标结果
     var i = 1; //设置开始扩展的下标,扩展时第一个参数不会进行改变,不需要遍历
     var length = arguments.length;
     var option;
     if(typeof target !== 'object') {
       target = {};
     }
     
     for(; i< length; i++){
       option = arguments[i]
       for(var name in option){
         target[name] = option[name]
       }
     }
     return target
   }
   
   //调用
   var i = {a: 0};
   var b = {c: 9};
   console.log($().extend(i,b)) // {a:0, c:9}


升级版本1.0, 对复杂对象进行扩展。

在上面,我们已经写出的extend的基础版本,但是如果我们简单测试一下,就会发现仍是有问题存在的。
我们可以使用上面的方法,对下面的对象进行扩展

      var n = {
        al: 90,
        m: {
          d: 23,
        }
      }
      var b = {m:{
        c: 98
      }};
      console.log($().extend(n,b)) // {al: 90, m: { c: 98 }}

简单的从结果来看,返回的结果并不符合我们的预期,基础版本的方法似乎只是简单的值替换而已。那么来简单升级一下代码吧。
在升级代码之前,需要了解一下关于浅拷贝和深拷贝的相关。


关于浅拷贝和深拷贝的那些事

浅拷贝

对于浅拷贝,我的简单理解就是: 浅拷贝就是对最表面的层级进行拷贝,如果某一被拷贝对象的值发生了改变,最终的拷贝结果也会随之发生改变。

      var i = {a: 0};
      var b = {c: 9};
      console.log($().extend(i,b)) // {a: 90, c:9}
      i.a = 90

深拷贝

深拷贝主要的是面对复杂对象,如果浅拷贝是对最表面的一层进行拷贝,那么深拷贝就是,对拷贝对象的每一个层级都进行拷贝,某种层面来说,勉强算得上是递归的浅拷贝吧,但是比较不同的是,深拷贝中,如果某一个被拷贝对象的值发生了改变,拷贝结果是不会随之发生变化的,是一个独立的存储空间。

   var n = {
     al: 90,
     m: {
       d: 23,
     }
   }
   var b = {m:{
     c: 98
   }};
   console.log($().extend(true,{},n,b))
   console.log(n)
   n.al = "cs"

结果:


深拷贝extend代码扩展

jQuery.extend是提供深拷贝的,需要将第一参数传为true。
基本思路:首先先对第一个传入参数进行判断,判断是否是boolean类型,来决定是否需要进行深拷贝;

   var deep = false;
   if (typeof target === 'boolean') {
     deep = target;
     target = arguments[1];
     i = 2;  //因为第一参数为boolean,所以拷贝对象从argument[1]开始,但通常第一个拷贝对象是不需要比遍历的,所以遍历下标从2开始。
   }

对需要遍历的对象进行判断,判断是否是复杂类型。使用extend对jquery进行扩展。

   if (length === i) { //此时extend参数只有一个,但是目标应该是this,所以获取到this;
     target = this;  //但同时 i = 1;无法进行遍历,所以将遍历下标后退一位
     i--;
   }
   
   jQuery.extend({
     isArray: function(obj) {
       return toString.call(obj) === '[object Array]';
     },
     isPainObj: function(obj) {
       return toString.call(obj) === '[object Object]';
     }
   })

extend方法改造。

   jQuery.prototype.extend = jQuery.extend = function(){
     var target = arguments[0] || {};
     var i = 1;
     var length = arguments.length;
     var option, copy, src, copyisArray, clone;
     for(; i< length; i++){
       if((option = arguments[i]) != null ){
         for(name in option) {
           src = target[name];
           copy = option[name];
           if(jQuery.isPainObj(copy) || (copyisArray = jQuery.isArray(copy))) {
             if(copyisArray) {
               copyisArray = false;
               clone = src && jQuery.isArray(src) ? src : [];
             } else {
               clone = src && jQuery.isPainObj(src) ? src : {};
             }
             target[name] = jQuery.extend(clone,copy)
           } else if(copy !== undefined) {
             target[name] = copy
           }
         }
       }
     }
     return target
   }

行了,到这里为止,我们就已经完成了简单的extend函数了,其实比较重要的是深拷贝和浅拷贝,关于这一点,下次再记录吧。


链接: https://www.fly63.com/article/detial/5185

Js中的 forEach 源码

在日常 Coding 中,码农们肯定少不了对数组的操作,其中很常用的一个操作就是对数组进行遍历,查看数组中的元素,然后一顿操作猛如虎。今天暂且简单地说说在 JavaScript 中 forEach。

微信小程序代码源码案例大全

克隆项目代码到本地(git应该都要会哈,现在源码几乎都会放github上,会git才方便,不会的可以自学一下哦,不会的也没关系,gitHub上也提供直接下载的链接);打开微信开发者工具;

Node 集群源码初探

随着这些模块逐渐完善, Nodejs 在服务端的使用场景也越来越丰富,如果你仅仅是因为JS 这个后缀而注意到它的话, 那么我希望你能暂停脚步,好好了解一下这门年轻的语言,相信它会给你带来惊喜

Vue源码之实例方法

在 Vue 内部,有一段这样的代码:上面5个函数的作用是在Vue的原型上面挂载方法。initMixin 函数;可以看到在 initMixin 方法中,实现了一系列的初始化操作,包括生命周期流程以及响应式系统流程的启动

vue源码解析:nextTick

nextTick的使用:vue中dom的更像并不是实时的,当数据改变后,vue会把渲染watcher添加到异步队列,异步执行,同步代码执行完成后再统一修改dom,我们看下面的代码。

React源码解析之ReactDOM.render()

React更新的方式有三种:(1)ReactDOM.render() || hydrate(ReactDOMServer渲染)(2)setState(3)forceUpdate;接下来,我们就来看下ReactDOM.render()源码

React源码解析之ExpirationTime

在React中,为防止某个update因为优先级的原因一直被打断而未能执行。React会设置一个ExpirationTime,当时间到了ExpirationTime的时候,如果某个update还未执行的话,React将会强制执行该update,这就是ExpirationTime的作用。

扒开V8引擎的源码,我找到了你们想要的前端算法

算法对于前端工程师来说总有一层神秘色彩,这篇文章通过解读V8源码,带你探索 Array.prototype.sort 函数下的算法实现。来,先把你用过的和听说过的排序算法都列出来:

vuex源码:state及strict属性

state也就是vuex里的值,也即是整个vuex的状态,而strict和state的设置有关,如果设置strict为true,那么不能直接修改state里的值,只能通过mutation来设置

webpack 源码从零开始:apable模型

最近在看webpack的源码,发现有个比较头疼的点是:代码看起来非常跳跃,往往看不到几行就插入一段新内容,为了理解又不得不先学习相关的前置知识。层层嵌套之后,发现最基础的还是tapable模型,因此先对这部分的内容做一个介绍。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!