1.체인콜이란
이해하기 쉽습니다. 예:
$(this).setStyle('color', 'red').show();
일반 함수 호출과 체인 호출의 차이점: 메소드 호출 후 return은 현재 호출하는 메소드의 객체를 반환합니다.
function Dog(){ this.run= function(){ alert("The dog is running...."); return this;//返回当前对象 Dog }; this.eat= function(){ alert("After running the dog is eatting...."); return this;//返回当前对象 Dog }; this.sleep= function(){ alert("After eatting the dog is running...."); return this;//返回当前对象 Dog }; } //一般的调用方式; /* var dog1 =new Dog(); dog1.run(); dog1.eat(); dog1.sleep();*/ var dog2 = new Dog(); dog2.run().eat().sleep();
2. 연쇄 호출 분해
체인 콜은 실제로 두 부분으로 구성됩니다.
1) Operation 객체(즉, 위의 예에서 $(this)와 같이 조작되는 DOM 요소)
2) 작업 방법(위 예의 setStyle 및 show와 같이 구체적으로 수행할 작업)
작업 객체 및 작업 방법 구현 방법
일반 $함수 만들기:
function $(){ var elements = []; for(var i= 0,len=arguments.length; i<len; i++){ var element = arguments[i]; if(typeof element==='string'){ element = document.getElementById(element); } if(arguments.length==1){ return element; } elements.push(element); } return elements; }
그러나 이 함수를 생성자로 변환하는 경우 해당 요소를 인스턴스 속성에 배열로 저장하고 생성자 함수의 프로토타입 속성이 가리키는 객체에 정의된 모든 메서드가 반환되어 메서드를 호출하도록 합니다. 해당 인스턴스에 연결하면 호출을 연결하는 기능이 있습니다. (말이 너무 많아서 이것을 반환하세요. 각 메서드의 마지막에),
먼저 이 $function을 체인 호출을 지원하는 개체 생성을 담당하는 팩토리 메서드로 변경해야 합니다. 이 함수는 이전과 동일한 공용 인터페이스를 사용할 수 있도록 요소 배열 형식의 인수를 받아들일 수 있어야 합니다. 이런 식으로 체인콜을 할 수 있는 능력이 있습니다.
변형은 다음과 같습니다.
(function(){ function _$(els){ this.elements = [];//把那些元素作为数组保存在一个实例属性中, for(var i= 0, len=els.length; i<len; i++){ var element = els[i]; if(typeof element==='string'){ element = document.getElementById(element); } this.elements.push(element); } } _$.prototype = { each: function(fn){ for(var i= 0,len=this.elements.length; i<len; i++){ fn.call(this, this.elements[i]); } return this; //在每个方法的最后return this; }, setStyle: function(prop, val){ this.each(function(el){ el.style[prop] = val; }); return this; //在每个方法的最后return this; }, show: function(){ var that = this; this.each(function(el){ that.setStyle('display', 'block'); }); return this; //在每个方法的最后return this; }, addEvent: function(type, fn){ var add = function(el){ if(window.addEventListener){ el.addEventListener(type, fn, false); }else if(window.attachEvent){ el.addEvent('on'+type, fn); } }; this.each(function(el){ add(el); }); return this; //在每个方法的最后return this; } } window.$ = function(){ return new _$(arguments); } })();
호출 메서드의 개체를 호출 체인의 다음 메서드에 전달하는 마지막에 이를 반환합니다.
3. jquery 기본 체인 프로그래밍 시뮬레이션
// 块级作用域 //特点1 程序启动的时候 里面的代码直接执行了 //特点2 内部的成员变量 外部无法去访问 (除了不加var修饰的变量) (function(window , undefined){ // $ 最常用的对象 返回给外界 大型程序开发 一般使用'_'作为私用的对象(规范) function _$(arguments){ //实现代码...这里仅实现ID选择器 // 正则表达式匹配id选择器 var idselector = /#\w+/ ; this.dom ; // 此属性 接受所得到的元素 // 如果匹配成功 则接受dom元素 arguments[0] = '#inp' if(idselector.test(arguments[0])){ this.dom = document.getElementById(arguments[0].substring(1)); } else { throw new Error(' arguments is error !'); } }; // 在Function类上扩展一个可以实现链式编程的方法 Function.prototype.method = function(methodName , fn){ this.prototype[methodName] = fn ; return this ; //链式编程的关键 } // 在_$的原型对象上 加一些公共的方法 _$.prototype = { constructor : _$ , addEvent:function(type,fn){ // 给你的得到的元素 注册事件 if(window.addEventListener){// FF this.dom.addEventListener(type , fn); } else if (window.attachEvent){// IE this.dom.attachEvent('on'+type , fn); } return this ; }, setStyle:function(prop , val){ this.dom.style[prop] = val ; return this ; } }; // window 上先注册一个全局变量 与外界产生关系 window.$ = _$ ; // 写一个准备的方法 _$.onReady = function(fn){ // 1 实例化出来_$对象 真正的注册到window上 window.$ = function(){ return new _$(arguments); }; // 2 执行传入进来的代码 fn(); // 3 实现链式编程 _$.method('addEvent',function(){ // nothing to do }).method('setStyle',function(){ // nothing to do }); }; })(window); // 程序的入口 window传入作用域中 $.onReady(function(){ var inp = $('#inp'); //alert(inp.dom.nodeName); //alert($('#inp')); inp.addEvent('click',function(){ alert('我被点击了!'); }).setStyle('backgroundColor' , 'red'); });
4. 콜백 함수를 사용하여 체인 호출을 지원하는 메서드에서 데이터를 얻습니다
연쇄 호출은 할당자 메서드에 매우 적합하지만, 값 게터 메서드의 경우 각 메서드가 이를 반환하기 때문에 불편합니다.
그러나 여전히 해결 방법이 있는데, 바로 콜백 함수입니다.
콜백 기능을 사용하지 않는 경우
//without callback window.API = window.API || function(){ var name = 'JChen'; this.setName = function(newName){ name = newName; return this; }; this.getName = function(){ return name; }; }; var o = new API(); console.log(o.getName()); console.log(o.setName('Haha').getName());
콜백 기능 사용 시
//with callback window.API2 = window.API2 || function(){ var name = 'JChen'; this.setName = function(newName){ name = newName; return this; }; this.getName = function(callback){ callback.call(this, name); return this; }; }; var o2 = new API2(); o2.getName(console.log).setName('Hehe').getName(console.log);
콜백 함수를 사용할 때는 일반적으로 callback.call(this, name)이 괜찮지만, 이 예제에서는 console.log를 사용하므로 문제가 있습니다. 그 이유는 이 콘솔이 winodw가 아닌 콘솔을 가리키기 때문입니다.
이 문제도 해결하기 쉽습니다. 다음과 같습니다:
//with callback window.API2 = window.API2 || function(){ var name = 'JChen'; this.setName = function(newName){ name = newName; return this; }; this.getName = function(callback){ callback.call(this, name); return this; }; }; var o2 = new API2(); var log = function(para){ console.log(para); }; o2.getName(log).setName('Hehe').getName(log);
이러한 체인 호출 스타일은 코드 작성을 단순화하여 코드를 더 간결하고 읽기 쉽게 만들고, 개체 변수를 여러 번 재사용하는 것을 방지합니다. 모두가 이 방법을 익힐 수 있기를 바랍니다.