手机版

用例子详细解释jQuery的新自由结构

时间:2021-09-08 来源:互联网 编辑:宝哥软件园 浏览:

jQuery的无新构造

jQuery框架的核心是匹配HTML文档中的元素并对其执行操作。

回想一下使用jQuery时实例化jQuery对象的方法:

//没有新的构造$('#test ')。文本('测试');//当然也可以使用new var test=new $(' # test ');Test . text(' Test ');大多数人使用jQuery直接用$(' ')构造,这对于jQuery来说是一个非常方便的地方。

当我们使用第一种没有new的构造方法时,它的本质相当于new jQuery(),那么它是如何在jQuery内部实现的呢?看一下:

(函数(窗口,未定义){ var //.jQuery=function(selector,context){//jQuery对象实际上只是init构造函数‘增强’返回new jQuery.fn.init(selector,context,rootjQuery);},jquery . fn=jquery . prototype={ init :函数(选择器,上下文,rootjQuery) { //.} } jquery . fn . init . prototype=jquery . fn;})(窗口);没听懂?没关系,我们一步一步来分析。

函数表达式和函数声明

在ECMAScript中,创建函数最常用的两种方法是函数表达式和函数声明。它们之间的区别有点模糊,因为ECMA规范只明确了一点:函数声明必须有一个标识符(也就是大家常说的函数名),而函数表达式可以省略这个标识符:

//函数声明:函数名(参数:可选){函数体}//函数表达式:函数名(可选)(参数:可选){函数体}因此可以看出,如果没有声明函数名,那一定是表达式,但是如果声明了函数名,那怎么判断是函数声明还是函数表达式呢?

ECMAScript通过上下文来区分。如果function foo(){}是赋值表达式的一部分,那么它就是一个函数表达式。

如果函数foo(){}包含在函数体中或位于程序的顶部,则它是一个函数声明。

function foo(){} //声明,因为它是程序var bar=function foo(){ };//表达式,因为它是赋值表达式的一部分,新建函数bar(){ };//表达式,因为它是新的表达式(由function(){ function bar(){} //声明,因为它是function body的一部分})();还有一种函数表达式不是很常见,就是(function foo(){}),这是一个表达式,因为括号()是分组运算符,里面只能包含表达式。

让我们看看jQuery源代码:

(函数(窗口,未定义){/.}) (window)可以把上面的代码结构分成两部分:(function(){window,undefined})和(window)。

第一个()是一个表达式,这个表达式本身就是一个匿名函数。

因此,在这个表达式后添加(window)意味着执行这个匿名函数并传入参数窗口。

原型原型

知道什么是原型。

在JavaScript中,原型也是对象,对象属性的继承可以通过原型来实现。JavaScript对象都包含一个内部属性“[[Prototype]]”,它对应于对象的原型。

属性“prototype”和“proto__”有时可能会混淆,“Person.prototype”和“Person”。_ _ proto _ _ _ '完全不同。

下面简单介绍一下“原型”和“__proto__”:

1.对于所有对象,都有一个__proto__属性,它对应于对象的原型

2.对于函数对象,除了__proto__属性,还有一个原型属性。当函数用作构造函数来创建实例时,函数的原型属性值将作为原型分配给所有对象实例(即,设置实例的__proto__属性)

函数Person(姓名、年龄){ this.name=namethis.age=年龄;} person . prototype . Getinfo=function(){ console . log(this . name '是' this . age ' age ' old ');};//调用var will=new Person('Will ',28);will . getinfo();//“威尔28岁了”的结尾

封闭的定义:

当内部函数被外部函数以外的变量引用时,就形成了闭包。

闭包的功能:

在理解闭包的功能之前,我们先来看看javascript中的GC机制:

在javascript中,如果一个对象不再被引用,它将被GC回收,否则它将一直存储在内存中。

在上面的例子中,b定义在a中,所以b依赖于a,外部变量c引用b,所以a被c间接引用,

也就是说,a不会被GC回收,而是会一直存储在内存中。为了证明我们的推理,请看下面的例子:

函数A(){ var count=0;函数B(){ count;console.log(计数);}返回B;} var c=A();c();//1c();//2c();//3count是A中的一个变量,它的值在B中是变化的,每次执行函数B时,count的值都会在原来的基础上累加1。因此,中的计数始终存储在内存中。

这就是闭包的功能。有时我们需要在一个模块中定义这样一个变量:我们希望这个变量将一直存储在内存中,但不会“污染”全局变量。此时,我们可以用闭包来定义这个模块。

查看jQuery源代码:

(函数(窗口,未定义){ var //.jQuery=function(selector,context){//jQuery对象实际上只是init构造函数‘增强’返回new jQuery.fn.init(selector,context,rootjQuery);},jquery . fn=jquery . prototype={ init :函数(选择器,上下文,rootjQuery) { //.} } jquery . fn . init . prototype=jquery . fn;})(窗口);我们知道什么是闭包:当内部函数被外部函数以外的变量引用时,就形成了闭包。

jQuery.fn的init函数被jQuery的构造函数调用,在这里形成了一个闭包。构造函数和调用代码:

//.jQuery=function(selector,context){//jQuery对象实际上只是init构造函数‘增强’返回new jQuery.fn.init(selector,context,rootjQuery);},问题的关键来了。

没有新的怎么建

JavaScript是一种函数式语言,函数可以实现类,这是面向对象编程中最基本的概念

Var a query=函数(选择器,上下文){//构造函数} aquery . prototype={//prototype name : function(){ },age : function(){ } } var a=new a query();a . name();这是一种正常的使用方式,很明显jQuery不会这样玩

为此,jQuery应该被视为一个类,然后$()应该返回该类的一个实例

根据jQuery的表达式,

$().ready() $()。noConflict()要实现这一点,jQuery应该被视为一个类,所以$()应该是返回类的一个实例

所以改变代码:

var aQuery=function(选择器,上下文){ return new aQuery();}一个查询。prototype={ name : function(){ },age:function () {}}通过new aQuery(),虽然返回了一个例子,但是可以看出有一个很明显的问题,那就是无限循环!

那么如何返回一个正确的实例呢?

在javascript中,这个实例只与原型相关

然后,您可以创建一个jQuery类的实例作为工厂方法,并将这个方法放在aQuery.prototye的原型中

var aQuery=function(选择器,上下文){ return aQuery.prototype.init(选择器);} AqEry . prototype={ init : function(选择器){ return this} name:function () {},age:function () {}}执行aQuery()时返回的实例:

显然,aquerry()返回了一个aquerry类的实例,所以init中的这个实际上是一个指向的aquerry类的实例。

问题来了。init的这一部分指向了aQuery类。如果init函数也被用作构造函数,那么在内部应该如何处理呢?

var aQuery=function(选择器,上下文){ return aQuery.prototype.init(选择器);}aQuery.prototype={ init:函数(选择器){ this.age=18返回this},名称为:function () {},年龄为:20} aQuery()。age//18因为这只指向aquery类,所以可以修改aQuery的age属性。

这看起来没问题,但实际上是个大问题

为什么是新的jQuery.fn.init?

请看下面的代码:

var aQuery=函数(选择器,上下文){ return aQuery.prototype.init(选择器);} aquery。prototype={ init :函数(选择器){ if(选择器==' a ')这个。年龄=18岁还这个;},name: function() {},age: 20}aQuery('a ').age //18aQuery('b ').年龄//18当我调用传入a的时候,修改年龄=18岁,及神曲.年龄的值为18

但是当我传入' b '的时候并没又修改年龄的值,我也希望得到默认年龄的值20,但是水性(' b ').年龄的值为18.

因为在调用神曲.年龄的时候年龄被修改了。

这样的情况下就出错了,所以需要设计出独立的作用域才行。

jQuery框架分隔作用域的处理

jQuery=函数(选择器,上下文){//jQuery对象实际上只是初始化构造函数'增强'返回new jQuery.fn.init(选择器、上下文、rootjQuery);},很明显通过实例初始化函数,每次都构建新的初始化实例对象,来分隔这个,避免交互混淆

我们修改一下代码:

var aQuery=函数(选择器,上下文){返回新的aQuery。原型。初始化(选择器);} aquery。prototype={ init :函数(选择器){ if(选择器==' a ')这个。年龄=18岁还这个;},name: function() {},age: 20}aQuery('a ').age //18aQuery('b ').年龄//未定义的年龄(' a ').name()//未记录的类型错误:对象[对象对象]没有方法"名称"又出现一个新的问题,

年龄:未定义,

名称():抛出错误,无法找到这个方法,所以很明显新的的初始化跟jquery类的这分离了

怎么访问jQuery类原型上的属性与方法?

做到既能隔离作用域还能使用jQuery原型对象的作用域呢,还能在返回实例中访问jQuery的原型对象?

实现的关键点

//给初始化函数jQuery原型,以便以后实例化jQuery。fn。初始化。prototype=jQuery。fn;我们再改一下:

var aQuery=函数(选择器,上下文){返回新的aQuery。原型。初始化(选择器);} aquery。prototype={ init :函数(选择器){ if(选择器==' a ')这个。年龄=18岁还这个;},name : function(){ return age;},年龄:20 }岁。原型。初始化。原型=水。原型;神曲.age //18aQuery('b ').年龄//20岁.name() //20最后在看一下jQuery源码:

(函数(窗口,未定义){ var //.jQuery=函数(选择器,上下文){//jQuery对象实际上只是初始化构造函数'增强'返回new jQuery.fn.init(选择器、上下文、rootjQuery);},jquery。fn=jquery。原型={ init :函数(选择器,上下文,rootjQuery) { //.} } jquery。fn。初始化。prototype=jquery。fn;})(窗口);是不是明白了?

哈哈哈~~~

在简单说两句:

大部分人初看jquery。fn。初始化。prototype=jquery。【数学】函数这一句都会被卡主,很是不解。但是这句真的算是jQuery的绝妙之处。理解这几句很重要,分点解析一下:

1)首先要明确,使用$('xxx ')这种实例化方式,其内部调用的是返回新的jQuery.fn.init(选择器、上下文、rootjQuery)这一句话,也就是构造实例是交给了jQuery.fn.init()方法取完成。

2)将jQuery.fn.init的原型属性设置为jQuery.fn,那么使用新建jQuery.fn.init()生成的对象的原型对象就是jQuery.fn,所以挂载到jQuery.fn上面的函数就相当于挂载到jQuery.fn.init()生成的jQuery对象上,所有使用新建jQuery.fn.init()生成的对象也能够访问到jQuery.fn上的所有原型方法。

3)也就是实例化方法存在这么一个关系链

1 .jquery。fn。初始化。prototype=jquery。fn=jquery。原型;

2.new jQuery.fn.init()相当于new jQuery();

3.jQuery()返回的是new jQuery.fn.init(),而var obj=new jQuery(),所以这2者是相当的,所以我们可以无新的实例化jQuery对象。

总结

以上就是jQuery的无新的构建的全部内容,希望本文对大家学习jQuery有所帮助。也请大家继续支持我们。

版权声明:用例子详细解释jQuery的新自由结构是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。