jQuery $ 原理及extend函数源码实现

栏目: jQuery · 发布时间: 6年前

内容简介:jQuery在页面直接通过$调用一开始的思考是这样实现,打印$可以直接打印出jQuery构造函数,但是当创建jQuery实例对象的时候,会进入一个死循环如何避免这一问题呢,这里要用到共享原型的设计,将jQuery原型对象上面扩展一个init方法,该方法的原型对象指向jQuery的原型对象

jQuery在页面直接通过$调用

  1. $ 就是jQuery的别称
  2. 通过 $() 创建jQuery的实例对象

实现

(function(root){
    var jQuery = function(){
        return new jQuery()
    }
    root.$ = root.jQuery = jQuery
})(this)

console.log($)
复制代码

一开始的思考是这样实现,打印$可以直接打印出jQuery构造函数,但是当创建jQuery实例对象的时候,会进入一个死循环

console.log($())    //不停的调用jQuery构造函数
复制代码

如何避免这一问题呢,这里要用到共享原型的设计,将jQuery原型对象上面扩展一个init方法,该方法的原型对象指向jQuery的原型对象

(function(root){
    var jQuery = function(){
        return new jQuery.prototype.init()  //返回的是init实例对象,该原型对象跟jQuery原型对象相等
    }
    jQuery.prototype = {
        init: function(){
        },
    }
    //共享原型对象
    jQuery.prototype.init.prototype = jQuery.prototype
    root.$ = root.jQuery = jQuery
})(this)
复制代码

当再次打印出$(),返回的是init的实例对象,想要扩展jQuery方法,只需要在jQuery.prototype上面扩展方法即可,init实例对象也能访问该方法

(function(root){
    var jQuery = function(){
        return new jQuery.prototype.init()  //返回的是init实例对象,该原型对象跟jQuery原型对象相等
    }
    jQuery.prototype = {
        init: function(){
        },
        method: function(){
            return 123
        }
    }
    //共享原型对象
    jQuery.prototype.init.prototype = jQuery.prototype
    root.$ = root.jQuery = jQuery
})(this)

console.log($().method())   //123
复制代码

extend

jQuery的extend有很多种调用方法

//任意对象扩展
var obj = $.extend({},{name: "ys"})

//往其本身扩展
$.extend({
   work: function(){}
})
jQuery.work()

//实例对象扩展
$.fn.extend({
    sex: "男"
})
jQuery().sex  //男
复制代码

任意对象扩展

(function(root){
    var jQuery = function(){
        return new jQuery.prototype.init()  //返回的是init实例对象,该原型对象跟jQuery原型对象相等
    }
    jQuery.prototype = {
        init: function(){

        },
        method: function(){
            return 123
        }
    }
    jQuery.extend = function(){
        var targe = arguments[0] || {}
        var length = arguments.length
        var i = 1
        var option, name
        if(typeof targe !== "object"){
            targe = {}
        }
        for(;i<length;i++){
            if((option = arguments[i]) != null){
                for(name in option){
                    targe[name] = option[name]
                }
            }
        }
        return targe
    }
    //共享原型对象
    jQuery.prototype.init.prototype = jQuery.fn
    root.$ = root.jQuery = jQuery
})(this)

var obj = $.extend({sex: "男"},{name: "ys"})   //{sex: "男", name: "ys"}
复制代码

本身扩展及实例对象扩展

实例对象扩展展只需要将jQuery.fn = jQuery.prototype 以及 jQuery.fn.extend = jQuery.extend

(function(root){
    var jQuery = function(){
        return new jQuery.prototype.init()  //返回的是init实例对象,该原型对象跟jQuery原型对象相等
    }
    jQuery.fn = jQuery.prototype = {
        init: function(){

        },
        method: function(){
            return 123
        }
    }
    jQuery.fn.extend = jQuery.extend = function(){
        var targe = arguments[0] || {}
        var length = arguments.length
        var i = 1
        var option, name
        if(typeof targe !== "object"){
            targe = {}
        }
        //参数个数等于1,说明是往自身扩展
        if(i === length){
            targe = this
            i--
        }
        for(;i<length;i++){
            if((option = arguments[i]) != null){
                for(name in option){
                    targe[name] = option[name]
                }
            }
        }
        return targe
    }
    //共享原型对象
    jQuery.prototype.init.prototype = jQuery.fn
    root.$ = root.jQuery = jQuery
})(this)

var obj = $.fn.extend({sex: "男"},{name: "ys"})   //{sex: "男", name: "ys"}

//往其本身扩展
$.extend({
    work: function(){
        return '搬砖'
    }
})
console.log(jQuery.work())  //搬砖
复制代码

进阶

extend方法还接受一个deep属性,指示是否深度合并对象,如果只是按上面的代码扩展对象,重复的属性会被覆盖,而不是合并

var obj1 = {
    name: "ys",
    attr: {
        age: "18"
    }
}
var obj2 = {
    name: "ys",
    attr: {
        sex: "男"
    }
}
var obj = $.extend(true, {}, obj1, obj2)

//后面得属性会覆盖之前的属性
console.log(obj)    //{name: "ys", attr: {sex: "男"}}
复制代码

如何才能对象合并而不是覆盖,以及做到对象的深拷贝呢? 接受的第一个参数传deep,true跟false

(function(root){
    var jQuery = function(){
        return new jQuery.prototype.init()  //返回的是init实例对象,该原型对象跟jQuery原型对象相等
    }
    jQuery.fn = jQuery.prototype = {
        init: function(){

        },
        method: function(){
            return 123
        }
    }
    jQuery.fn.extend = jQuery.extend = function(){
        var targe = arguments[0] || {}
        var length = arguments.length
        var i = 1
        var deep = false
        var option, name, copy, src, copyIsArr, clone
        //深拷贝,浅拷贝
        if(typeof targe === "boolean"){
            deep = targe
            targe = arguments[1] || {}  //为了不改变之前的步骤,将参数第二项赋给target,并且将i改为2
            i = 2
        }
        if(typeof targe !== "object"){
            targe = {}
        }
        //参数个数等于1,说明是往自身扩展
        if(i === length){
            targe = this
            i--
        }
        for(; i < length; i++){
            if((option = arguments[i]) != null){
                for(name in option){
                    copy = option[name]
                    src = targe[name]
                    if(deep && copy && (copy instanceof Object || (copyIsArr = copy instanceof Array))){//判断是否是深拷贝及浅拷贝,copyIsArr判断是否是数组
                        if(copyIsArr){  //copy是数组
                            copyIsArr = false
                            clone = src && src instanceof Array ? src : []
                        } else {
                            clone = src && src instanceof Object ? src : {}
                        }
                        targe[name] = jQuery.extend(deep, clone, copy)  //递归调用,深拷贝
                    } else if(copy){
                        targe[name] = copy
                    }
                }
            }
        }
        return targe
    }
    //共享原型对象
    jQuery.prototype.init.prototype = jQuery.fn
    root.$ = root.jQuery = jQuery
})(this)

//两层
var obj1 = {
    name: "ys",
    attr: {
        age: "18"
    }
}
var obj2 = {
    name: "ys",
    attr: {
        sex: "男"
    }
}
var obj = $.extend(true, {}, obj1, obj2)
console.log(obj)    //{name: "ys", attr: {age: "18", sex: "男"}}

//三层
var obj1 = {
    name: "ys",
    attr: {
        age: {
            a: 1
        }
    }
}
var obj2 = {
    name: "ys",
    attr: {
        sex: "男",
        age: {
            b: 2
        }
    }
}
var obj = $.extend(true, {}, obj1, obj2)
console.log(obj)     //{name: "ys", attr: {age: {a: 1, b: 2}, sex: "男"}}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Django 1.0 Template Development

Django 1.0 Template Development

Scott Newman / Packt / 2008 / 24.99

Django is a high-level Python web application framework designed to support the rapid development of dynamic websites, web applications, and web services. Getting the most out of its template system a......一起来看看 《Django 1.0 Template Development》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具