前言:在这mvvm模式盛行的今天,很多人觉得没必要去了解jquery源码,而我并不认同以上的说法。jquery对javaScript进行了封装使其更加完善,jquery的源码中更是能看到对js原生方法的完美运用,还能学到很多没见过的操作JavaScript的技巧。简单的说,学习源码能让JavaScript使用基础更扎实。
学习jquery源码需解决的几个问题。
①、jquery是如何做到里面定义的变量不暴露在全局,而且只暴露出来一个$操作符跟一个jQuery给我们调用。
②、jquery是如何做到不运用到new就可以实例化jquery对象的。
③、jquery是如果做到链式操作的。
一、问题①
我们无法直接访问jquery里面定义的变量,但是通过$操作符或者jQuery就可以进行访问了。
- (function(window,undefined){
- //第二个形参undefined是为了里面出现的变量名为undefined的变量值真的为undefined,而不是其他值
- var jQuery = function(){ //构造函数
- };
- window.jQuery = window.$ = jQuery;
- })(window);
利用匿名函数自执行,来形成全局无法直接访问的函数作用域,然后将全局的window,通过传参的方式传入到该函数作用域中。最后通过window.jQuery = jQuery,window.$ = jQuery的方式,将jQuery构造函数暴露出去。这样我们就可以通过jQuery和$访问该函数作用域里变量了。
二、问题②
jquery是如何做到不运用到new就可以实例化jquery对象的。
- function Person(name,age){
- this.init(name,age);
- };
- Person.prototype= {
- init: function(name,age){
- this.name = name;
- this.age = age;
- },
- sayName: function(){
- console.log('姓名: '+ this.name);
- },
- sayAge: function(){
- console.log('年龄: '+ this.age);
- }
- };
- var nick = new Person('nick',18); //实例化对象
- nick.sayName();
- nick.sayAge();
JavaScript中实例化一个对象需要通过new一个构造函数的方式是实现。而在jquery中我们可以直接通过类似$('.box')的方式直接实例出一个jQuery对象,并通过$('.box').css()的方式直接调用对象方法。这是怎么做到的。
现在来模拟jQuert中实现不用new实例化对象的写法
- (function(window,undefined){
- var jQuery = function(name,age){
- return new jQuery.prototype.init(name,age);
- };
- jQuery.prototype = {
- init: function(name,age){
- this.name = name;
- this.age = age;
- },
- sayName: function(){
- console.log('姓名: '+this.name);
- },
- sayAge: function(){
- console.log('年龄: '+this.age);
- }
- };
- jQuery.prototype.init.prototype = jQuery.prototype;
- window.jQuery = window.$ = jQuery;
- })( window );
- var nick = $('nick',18);
- nick.sayName();
- nick.sayAge();
- $('freddy',23).sayName();
- $('freddy',23).sayAge();
输出结果:
这样也就实现了不用再外面用new就可以实例化对象了。其中比较抽象的就是
- jQuery.prototype.init.prototype = jQuery.prototype;
了解过prototype也就知道,对象的实例化跟prototype原型密不可分。这里是把jQuery.prototype.init.protype的指向指回了jQuery.prototype。
我们在看回jquery源码中的写法
- (function(window,undefined){
- var jQuery = function(selector, context){
- return new jQuery.fn.init(selector, context, rootjQuery);
- };
- jQuery.fn = jQuery.prototype = {
- init: function(selector, context, rootjQuery){
- }
- }
- jQuery.fn.init.prototype = jQuery.fn;
- window.jQuery = window.$ = jQuery;
- })( window );
跟我们模拟的写法稍有不同的是,他让jQuery.fn = jQuert.prototype = {},让jQuery.fn指向了同一个原型对象,这样操作jQuery.fn等同于操作jQuery原型对象。