일반적인 프런트엔드 개발 작업에서는 js를 작성할 때 함수 콜백이 여러 곳에서 사용됩니다.
가장 간단한 예는 다음과 같습니다.
<script language="javascript" type="text/javascript"> function doSomething(callback) { if(typeof callback == "function") { callback(); } } function foo() { alert("我是回调后执行的函数"); } doSomething(foo); /*正确*/ doSomething(function(){ alert("我是回调后执行的函数"); }); /*正确*/ doSomething("foo"); /* 这样是不行的,传入的是一个字符串,不是一个函数名 */ </script>
위에서는 매개변수 없이 콜백만 가능합니다(콜백 함수의 매개변수를 미리 알지 않는 한). 함수에 알 수 없는 함수가 있으면 그렇게 간단하게 호출할 수 없습니다.
고급 방법:
1. javascript
function doSomething(callback,arg1,arg2) { callback.call(this,arg1,arg2); } function foo(arg1,arg2) { alert(arg1+":"+arg2); } doSomething(foo,1,2); /* 弹出了1:2 */
2의 호출 방법을 사용합니다.
function doSomething(callback,args) { callback.apply(window,args); } function foo(arg1,arg2) { alert(arg1+":"+arg2); } doSomething(foo,[1,2,3]); /* 弹出了1:2 */
의 적용 방법은 기본적으로 호출 및 적용과 동일하다고 간주할 수 있습니다. 매개변수를 하나씩 적용하고 배열의 매개변수만 전달할 수 있습니다.
첫 번째 매개변수는 모두 범위입니다. 예를 들어 위에서 전달한 경우 doSomething 함수와 동일한 범위를 의미합니다. 물론 전체 창의 범위를 의미하는 window도 전달할 수 있습니다.
3. Apply
apply의 영리한 사용은 특정 기능을 실행하는 데 사용되는 함수인 함수의 실행 함수라고도 볼 수 있습니다. 따라서 적용을 잘 사용하면 원래 복잡했던 많은 일이 너무 단순해지는 경우가 있다는 것을 알게 될 것입니다.
예를 들어 배열의 푸시 메소드는 적용을 사용하여 호출됩니다.
var arr1=[1,3,4];
var arr2=[3,4,5];
arr2를 확장하려는 경우 , 그런 다음 하나씩 arr1에 추가하고 마지막으로 arr1=[1,3,4,3,4,5]
arr1.push(arr2)를 허용하면 분명히 작동하지 않습니다. 이렇게 하면 [1,3,4,[3,4,5]]
루프를 사용하여 하나씩 푸시할 수 있기 때문입니다(물론 arr1.concat(arr2)도 사용할 수 있지만 concat 메소드는 arr1 자체를 변경하지 않습니다)
var arrLen=arr2.length for(var i=0;i<arrLen;i++){ arr1.push(arr2[i]); }
Apply가 도입된 이후로 모든 것이 매우 간단해졌습니다
Array.prototype.push.apply(arr1, arr2)
원칙은 코드 한 줄로 해결할 수 있습니다. 보시다시피 Array.prototype.push는 배열의 푸시 함수를 나타냅니다. apply(arr1, arr2)는 arr1이 배열의 푸시 함수를 호출하는 것과 동일함을 나타냅니다.
그리고 arr1은 실제로는 arr2는 입력 매개변수의 배열을 나타냅니다. 따라서 위의 명령문은 arr1.push(3,4,5)와 동일합니다. (푸시 함수는 다중 입력 매개변수 전달을 지원하며 이는 여기서 적용을 사용하기 위한 전제조건이기도 합니다.)
위 명령문은 다음과 같이 작성할 수도 있습니다: arr1.push.apply(arr1, arr2); arr1.push는 배열의 푸시 기능인 arr1의 푸시 기능을 나타내기 때문입니다.
call을 사용한다면 Array.prototype.push.call(arr1, arr2[0], arr2[1]...)과 같으니 당연히 적용해도 괜찮습니다.
그래도 묻는다면 arr1.push(3,4,5)를 사용하는 것이 어때요? 이는 귀하의 IQ를 노출시켰기 때문에 arr2를 변경할 수 없는 것은 아닙니다. ] 다음에는 모직물.
또한 배열에서 가장 큰 숫자를 얻으려면 Apply를 사용하여 Math.max 함수를 호출할 수도 있습니다.
var arr1=[1,3,4];
alert(Math.max.apply(window,arr1 )) ; /* 범위는 null일 필요는 없습니다. Math.max.apply(this, arr1), Math.max.apply(null, arr1) */
4에서 함수 콜백의 실제 예를 확인하세요. work
위의 기초를 바탕으로 직장에서 캡슐화된 js 콜백 기능을 이해할 수 있습니다
배경: 페이지 A는 페이지 B를 사용하여 특정 프로젝트를 선택한 다음 이 프로젝트의 정보를 페이지 A, 페이지 A로 다시 가져와야 합니다. 이 정보를 바탕으로 자신을 풍요롭게 만듭니다.
페이지 A:
noticeInfo = { selectProject: function () { var win = newsee.ui.window win.show('项目列表', '../Project/ProjectSelectList.html?callback=noticeInfo.setProjectInfo', { size: win.winSizeType.big }) //在当前页面弹出框,框里面是另一个页面,地址后面带上需要回调的函数名 //注意这两个页面其实都是在一个页面里面的,并不是像window.open()那样出现了新窗口,所以两个页面的js都是可见的 }, setProjectInfo: function (obj) { //回调函数,将选择好的项目对象传进来,然后丰富自己的页面 $('#projectName').val(obj.name) $('#projectID').val(obj.id) } }
페이지 B:
function SelectBack() { var callback = newsee.util.url.getQuery('callback'); //获取页面参数callback,这里获取到的是"noticeInfo.setProjectInfo",是个字符串 var arr = newsee.ui.grid.getSelectedBack('datagrid') //获取选择的项目,这个不用深究 if (!arr.length) { return newsee.ui.window.alert('请选择项目!') } newsee.util.url.back(callback, arr[0]) //重点来了,这里执行回调,将需要回调的函数名和入参传进来,arr[0]就是选择的项目的对象的数组了(它也是个数组,里面就一个对象) }
newsee.util.url.back 함수는 다음과 같습니다.
back : function (funcName) { // / <param name="funcName" type="String">返回时执行的方法,一般为重新绑定</param> var isWindow = typeof $$winClose === 'function',// 是否为弹窗 args // 弹窗返回方法参数 if (isWindow) {// 弹窗的返回方法 $$winClose() args = [].slice.call(arguments) //arguments大家应该都知道的吧,它可以用来获取函数的实参,它类似数组又不是数组,这句代码就是把它转换成数组,因为apply的入参需要是个数组才行 //args现在里面有两个元素,args[0]=callback,就是之前传进来的回调函数名,args[1]=arr[0],就是回调函数的入参 newsee.callFunc.apply(newsee, args) //执行 newsee.callFunc 函数,作用域就是newsee自己(等同于newsee自己调用callFunc函数),参数是args } }
newsee.callFunc 함수는 다음과 같습니다.
callFunc: function(funcName, arg) { var func = typeof funcName === 'function' ? funcName : this.findItem(window, funcName) //上面我有提到过,doSomething("foo"); 传入的是一个字符串,不是一个函数名,所以无法执行 //同样的道理,现在funcName=args[0]=callback="noticeInfo.setProjectInfo",是个字符串,不能直接调用apply,需要变成函数 //这句话就是用来判断funcName是不是一个函数,如果不是,就在window作用域里根据funcName找到这个函数,然后赋给func if (typeof func === 'function') { //此时func已经是个函数了,就是页面A里定义的noticeInfo.setProjectInfo() try { return func.apply(window, arg) //执行需回调的函数,作用域依然是window,反正这个函数在window里肯定能找到,参数就是arg=args[1]=arr[0],即之前在页面B获取到的项目对象 } catch (e) { console.error(e) } } }
ok, 콜백이 필요한 함수 문자열 형식의 함수 이름을 기반으로 이 함수를 가져오는 방법은 아래를 참조하세요.
//findItem函数如下: findItem: function(data, key) { // / <summary>获取对象指定键的值</summary> if (this.include(data, key)) { //data这里就是传进来的window,注意window就是一个对象,首先判断window对象里是否存在"noticeInfo.setProjectInfo"这个属性 return eval('data.' + key) //如果存在,就执行"data.noticeInfo.setProjectInfo",这样就获取到了这个函数了。(eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码) } } //include函数如下: include: function(data, key) { // / <summary>判断对象是否存在键值</summary> if (data == null || typeof data !== 'object' || !key || typeof key !== 'string') { return false } var keys = key.split('.'), item = data, result = true keys.forEach(function(k) { if (item != null && typeof item === 'object' && k in item) { //依次循环遍历,第一次item = data,那就是window这个对象,k="noticeInfo",window[noticeInfo]是存在的,因为在页面A里定义了noticeInfo这么一个对象 //第二次循环,item=window.noticeInfo,k="setProjectInfo",window.noticeInfo[setProjectInfo]也是存在的,因为在页面A里也定义了setProjectInfo这么一个函数 //这里没有第三次循环了,所以最后返回是true,说明window对象里存在"noticeInfo.setProjectInfo"这个属性,接下来使用eval()拿到它即可 item = item[k] } else { return result = false } }) return result }
또한 eval() 함수를 소개합니다.
eval() 함수는 특정 문자열을 계산하고 그 안에 있는 JavaScript 코드를 실행할 수 있습니다.
반환 값은 문자열(있는 경우)을 계산하여 얻은 값입니다. 예:
eval("x=10;y=20;document.write(x*y)") //输出 200 document.write(eval("2+2")) //输出 4 var x=10 document.write(eval(x+17)) //输出 27
그래서 위의 eval('data.' + key)는 "data.noticeInfo.setProjectInfo"라는 문자열을 실행하는 것입니다.
여기의 데이터는 window를 참조하므로 반환 값은 window.noticeInfo.setProjectInfo입니다. ( ) 이 함수
는 실제로 더 간단할 수 있습니다. 포함 함수에서 항목은 이미 window.noticeInfo.setProjectInfo 객체이고 이 객체는 우리가 사용하는 함수이기 때문입니다. 원하다. .
(js에서는 함수도 객체입니다. 함수 이름은 이 함수에 대한 참조로, 주소와 거의 같습니다)
이제 이 함수를 얻었으니 직접 반환하면 됩니다. 위의 include() 및 findItem은 다음과 같이 단순화할 수 있습니다.
include: function(data, key) { if (data == null || typeof data !== 'object' || !key || typeof key !== 'string') { }else{ var keys = key.split('.'), item = data, result = true keys.forEach(function(k) { if (item != null && typeof item === 'object' && k in item) { item = item[k] } else { result = false; } }) if(result) return item } }, findItem: function(data, key) { return this.include(data, key)
테스트 후 문자열 형식의 함수 이름을 기반으로 함수를 얻는 이 두 가지 방법은 정확히 동일한 효과를 얻을 수 있는 것으로 나타났습니다.
위 내용은 js 함수 콜백의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!