빈하 중농판 jQuery

27084 단어 jquery
전에 한 편JavaScript 네임스페이스의 글을 썼는데 다 쓴 후에 jQuery의 간단한 사용에 대한 부러움이 컸다. 다른 사람의 원본 코드를 보니 사용 원리가 유사하다. 이전 버전을 개선하고 간이판 jQuery를 만들었다.
이전 코드
(function () {
            var _NS = function () {
              
            }
         
            _NS.prototype.select = function (selector,context) {
                var context = context || document;
                return context.querySelectorAll(selector);
            }

            _NS.prototype.isArrayLike=function(obj){
                if(obj instanceof Array){
                    return true;
                }

                var length=obj.length;
                if ( obj.nodeType === 1 && length ) {
                    return true;
                }
                return false;
            }

            _NS.prototype.html = function (obj,value) {
                var isArray=this.isArrayLike(obj), i=0;

                if (typeof value == 'string') {
                    if (!isArray) {
                        obj.innerHTML = value;
                    } else {
                        var length = obj.length;
                        while (i < length) {
                            obj[i].innerHTML = value;
                            i += 1;
                        }
                    }
                } else {
                    if (!isArray) {
                        return obj.innerHTML;
                    } else {
                        return obj[0].innerHTML;
                    }
                }
            }

            window.NS = new _NS();
        })();

이러한 쓰기 방법은 여러 가지 사용자 정의 방법에 대한 격리일 뿐, 사용할 수 있을 뿐, 날로 유행하는 체인 호출은 지원되지 않으며, jQuery를 사용할 때 $(selector) 를 쉽게 쓸 수 있습니다.xxx().xxxx().xxxxx () 같은 형식의 코드는 간결하고 읽기 쉽고 효율이 높으며 위의 쓰기는 하나의 외딴 함수만 호출할 수 있고 대상의 전체성은 말할 수 없다.
위의 select 방법은 검색 대상으로 값을 되돌려줍니다. (IE 저버전 브라우저는 지원하지 않습니다.) 대상을 얻은 후에 라이브러리 함수를 사용하여 직접 조작하기를 원합니다. 예를 들어 페이지에 있는 모든div의 inner HTML을 테스트로 설정하고 이div를 숨기기를 원합니다. jQuery로 이렇게 쓰면
$(div).html('test').css(‘display’,’none’);

위의 코드는 css 방법을 실현하지 못했지만, 있으면 이렇게 써야 한다
var divs=NS.select('div');
divs.html('test');
divs.css('display','none');

왜 jQuery가 편해
jQuery가 사용하기 좋은 이유는 다음과 같습니다.
1. $자체는 function 대상이며'정적 방법'(실례화하지 않아도 사용할 수 있는 방법)을 포함한다. 예를 들어 $.ajax、$.animation, 이렇게 $.xxx () 는 jQuery의 일부 라이브러리 함수를 직접 사용합니다
2. $자체는 함수이기 때문에 호출될 수 있습니다.그러나 $(selector)가 결과를 되돌려주는 것은 검색 결과 집합이 아니라 jQuery 실례입니다. 결과 집합은 jQuery 대상에 봉인되어 있습니다. 그러면 일부 jQUery 실례 방법(즉prototype에 정의된 방법 등)을 사용할 수 있습니다. 예를 들어 $('div').html('test'), $('div')가 jQuery 실례를 되돌려주기 때문에 실례 방법인 html()을 호출할 수 있습니다.
3. jQuery 대상의 대부분 실례적인 방법은 가능한 한 jQuery 대상, 즉 호출자 자체를 되돌려줍니다. 이렇게 하면 $('div') 같은 체인 호출을 지원할 수 있습니다.html(‘test’).css('display','none'), $('div')는 jQuery 대상을 되돌려줍니다. 결과집을 포함하고 실례적인 방법인 html('test')를 호출하면 jQuery 대상을 되돌려주고 css('display','none')를 호출하면 jQuery 대상을 되돌려줍니다. 이렇게 계속 호출할 수 있습니다.
구조 함수의 일부 지식
위의 몇 가지를 하려면prototype 등 기본 지식을 제외하고 자바스크립트 구조 함수에 대한 지식도 알아야 한다.
1.어떤 함수가 구조함수인가
JavaScript의 세계에서 구조 함수는 신비롭지도 특수하지도 않다. 어떤 함수도 new 조작부호를 통해 호출하면 구조 함수로 변할 수 있다. new 조작부호를 사용하지 않으면 구조 함수가 아니라 일반 함수로 호출된다.
2. 구조 함수는 어떤 결과를 되돌려줍니까
구조 함수의 반환 값은 두 가지 상황으로 나뉜다.function에return 문장이 없거나return이 기본 형식(bool,int,string,undefined,null)을 반환할 때 new가 만든 익명 대상을 반환한다. 이 대상은 함수 실례이다.function 체내에 인용 형식 대상 (Array, Function, Object 등) 이 있으면, 이 대상은 new에서 만든 익명 대상을 덮어쓰고 되돌려줍니다.
작은 예를 써서 검증해 보다
function A(){
                return true;
            }
            
            var a=new A();
            console.log(a instanceof A); //true
            
            function B(){
                return new Array();
            }
            
            var b=new B();
            console.log(b instanceof Array); //true

빈농 버전 jQuery 만들기
위에서 말한 jQuery의 몇 가지 장점에 대해 버전을 써 보십시오. jQuery와 좀 더 비슷해지기 위해 반환 함수 이름도 $로 바꾸고 프레임워크를 먼저 쓰십시오.
version 0.1
(function(){
                var $=function(selector,context){
                    
                };
                
                $.ajax=function(configs){ //    
                    //TODO
                } 
                
                $.prototype.html=function(value){ //    
                    //TODO
                }
                
                window.$=$;
            })();

정적 방법과 실례적 방법의 일부분이 잘 이루어지면 버젼 0.1과 비슷한 모양으로 쓰면 됩니다. 이 버전에서는 $가 함수인 것은 맞지만 $(selector)가 $의 실례를 어떻게 실행하고 실례에 검색 결과를 포함하는지.다음 버전 쓰기
version0.2
(function(){
                var $=function(selector,context){
                    var context = context || document; 
                    var nodeList = context.querySelectorAll(selector); 
                    
                    var $=new $();
                    $.elements=nodeList;
                    return $;
                };
                
                $.ajax=function(configs){ //    
                    //TODO
                } 
                
                $.prototype.html=function(value){ //    
                    //TODO
                }
                
                window.$=$;
            })();

이것은 보기에 $는 함수입니다. 정적 방법이 있습니다. $(selector)는 $의 실례를 되돌려줍니다. 검색 결과 집합을 포함하지만, 이러한 방식은 문법적 오류가 있습니다. 코드에서 $function 체내에서 new 자신을 시도하고, new로 실행할 때 자바스크립트는 $를 인식하지 못합니다. 실패합니다.
다른 발상의 version 0.3을 시도할 수 있습니다.
(function(){
                function f(selector,context){
                    return ?;
                }
                
                var $=(function(){
                    return f;
                })();
                window.$=$;
            })();

이렇게 하면 $도 함수이지만, 어떻게 해야만 실행 결과를 그 자체의 실례로 되돌릴 수 있습니까? 즉, f는 도대체 $의 실례를 어떻게 되돌려야 합니까? 이렇게 여러 번 실례를 말했는데, 마침내 new의 대상을 직접 제외하고는 그 실례를 얻을 수 있고,prototype에서 정의한 함수는this 대상에 접근하여 되돌릴 수 있다는 것을 생각해 냈습니다.이것은 f의prototype 함수에서this로 되돌아오도록 요구한다. 끊임없이 바뀌고 조정이 마침내 이렇게 되었다
version 0.4
(function(){
                var $=(function(){    
                    function f(selector,context){
                        return f.prototype.init(selector,context);
                    }
                    
                    f.prototype.init=function(selector,context){
                        var context = context || document; 
                        var nodeList = context.querySelectorAll(selector); 
                        this.length = nodeList.length; 
                        this.elements=new Array();
                        for (var i = 0; i < this.length; i++) { 
                            this.elements[i] = nodeList[i]; 
                        } 
                        return this; 
                    }
                        
                    return f;
                })();
                
                window.$=$;
            })();

방금 사용자 정의한 함수를 기입합니다
version 1.0
(function(){
                var $=(function(){    
                    function f(selector,context){
                        return f.prototype.init(selector,context);
                    }
                    
                    f.ajax=function(configs){
                        //TODO
                    }
                    
                    f.prototype.init=function(selector,context){
                        var context = context || document; 
                        var nodeList = context.querySelectorAll(selector); 
                        this.length = nodeList.length; 
                        this.elements=new Array();
                        for (var i = 0; i < this.length; i++) { 
                            this.elements[i] = nodeList[i]; 
                        } 
,                        return this; 
                    }
                    
                    f.prototype.html=function(value){
                        //TODO
                    }
                        
                    return f;
                })();
                
                window.$=$;
            })();

이렇게 해서 마침내 모든 요구가 이루어졌다. 내부 익명 함수에서function f를 정의하고 마지막에 $에게 값을 부여한다. 그러면 $는 함수이고 실행할 때 층층이 호출되며 마지막에 f.protype로 호출된다.init를 되돌려줍니다. init에서 검색 결과를this의 속성에 넣고 마지막으로this를 되돌려줍니다. 그리고 f는this를 되돌려줍니다. 이렇게 $(selector)의 결과는 $대상의 실례이며 검색 결과를 포함합니다.
jQuery 소스 구조
위의 결과는 이미 매우 만족스럽다. 자세히 jQuery 원본을 읽고 jQuery 구조를 보아라
(function( window, undefined ) {
   
    var jQuery = (function() {
       //   jQuery  
       var jQuery = function( selector, context ) {
           return new jQuery.fn.init( selector, context, rootjQuery );
       }
   
       // jQuery    
       jQuery.fn = jQuery.prototype = {
           constructor: jQuery,
           init: function( selector, context, rootjQuery ) {
              // selector   7     :
              // DOM  
              // body(  )
              //    :HTML  、HTML   、#id、      
              //   (  ready    )
              //        
           }
       };
   
      // jQuery prototype   init   prototype
       jQuery.fn.init.prototype = jQuery.fn;
   
       //
       //   jQuery.fn.extend     ,         jQuery.extend       
       jQuery.extend = jQuery.fn.extend = function() {};
      
       //  jQuery       
       jQuery.extend({
           // ready bindReady
           // isPlainObject isEmptyObject
           // parseJSON parseXML
           // globalEval
           // each makeArray inArray merge grep map
           // proxy
           // access
           // uaMatch
           // sub
           // browser
       });

       return jQuery;
   
    })();
   
    window.jQuery = window.$ = jQuery;
})(window);

총체적으로는 일치하지만, jQuery의 구조는 매우 과학적이어야 한다
1. 윈도우 대상을 익명 함수에 전송하여 익명 함수 내부에 직접 접근할 수 있도록 하고, 익명 함수 내부에서 윈도우 대상을 사용할 때 역할 체인을 층층이 찾아야 마지막으로 윈도우를 찾을 수 있다.
2. 몽둥이로 때려죽이지 않고 $를 완전히 사용합니다. $명칭 충돌이 발생할 때 jQuery로 대체할 수 있습니다
3. jQuery를 정의합니다.fn=jQuery.prototype, 코드는 쓰기에 매우 편리하고 압축에도 유리하다
4.elements 속성을 사용하지 않고 수조 특성을 이용하여 검색 결과 집합을 봉인하여 사용할 때 생각하기 쉽다
5.each 함수를 결과 집합을 옮겨다니는 데 사용하기 정의
6. 대상 내부에 속성을 추가하는 extend 함수를 제공합니다
가난한 사람 버전 jQuery Version2.0
대사의 서법을 보고 드디어 빈농에서 벗어날 수 있게 되었다
(function () { 
                var $ = (function () { 
                    var $ = function (selector, context) { 
                        return new $.prototype.init(selector, context); 
                    }

                    $.prototype.init = function (selector, context) { 
                        var context = context || document; 
                        var nodeList = context.querySelectorAll(selector); 
                        this.length = nodeList.length; 
                        for (var i = 0; i < this.length; i++) { 
                            this[i] = nodeList[i]; 
                        } 
                        return this; 
                    }

                    $.prototype.each = function (callback, args) { 
                        var length = this.length, i = 0; 
                        if (args) { 
                            while (i < length) { 
                                callback.call(this[i], args); 
                                i += 1; 
                            } 
                        } else { 
                            while (i < length) { 
                                callback.call(this[i]); 
                                i += 1; 
                            } 
                        } 
                        return this; 
                    }

                    $.prototype.html = function (value) { 
                        if (typeof value == 'string') { 
                            this.each(function () { 
                                this.innerHTML = value; 
                            }); 
                            return this; 
                        } else { 
                            return this[0].innerHTML; 
                        } 
                    }

                    $.prototype.init.prototype = $.prototype;

                    return $; 
                })();

                window.$ = $; 
            })();

최후
본고는 제가 jQuery를 실현하고자 하는 과정을 정리하고 사고 구조가 혼란스러우니 독자를 오도하지 않기를 바랍니다.jQuery 원본을 여러 번 읽은 데다가 인터넷에서 많은 블로그 분석을 통해 jQuery를 한 걸음 한 걸음 똑똑히 볼 수 있다. jQuery의 디자인은 매우 교묘하다. 보통 사람들은 실현 방식을 한 번에 생각하기 어렵고 전망성이 있다. 언제나 jQuery 명명 공간이나 jQuery 실례를 사용해서 미래의 JavaScript 원생 API와 충돌하는 것을 방지하고 연구를 많이 하면 이익을 얻을 수 있다.

좋은 웹페이지 즐겨찾기