(3일) 함수

23833 단어

함수 정의


키워드 function은 함수를 정의하는 데 사용됩니다.함수를 정의하는 데는 두 가지 방법이 있다

(1) 함수 정의 표현식

1 var f = function(x) { return x+1; }

(2) 함수 성명문

1 function funcname([arg1 [, arg2 [...,argn]]]) {
2 
3 }

함수 성명문은 일반적으로 자바스크립트 코드의 맨 위에 나타나거나 다른 함수 안에 끼워 넣을 수 있다.그러나 중첩할 때, 함수 성명은 중첩된 함수의 맨 위에만 나타날 수 있습니다.즉, 함수 정의는if문장,while문장 후자의 다른 문장에 나타날 수 없다.

양자 공통점과 차이점


(1) 같은 새 함수 대상을 만들었습니다
(2) 함수 성명 문장의 함수 이름은 변수 이름이고 변수는 함수 대상을 가리킨다.함수 정의 표현식은 변수를 설명하지 않습니다. 함수 정의 표현식이 이름을 포함하면 함수의 국부 작용역은 함수 대상에 귀속된 이름을 포함합니다.그래서 명칭은 함수체에 존재하고 이 함수 자체를 가리킨다. 즉, 함수의 명칭은 함수 내부의 국부 변수가 될 것이다.[주] 함수 정의 표현식은 한 번만 사용할 수 있는 함수를 정의하는 데 특히 적합하다
(3) 함수 성명 문장의 함수는 스크립트나 함수 맨 위에 뚜렷하게 앞당겨졌다.그래서 그것들은 전체 스크립트와 함수 안에서 볼 수 있다.그러나 함수 표현식으로 함수를 정의하는 것은 다르다. 이 정의된 함수를 호출하려면 인용해야 하고, 표현식으로 정의된 함수를 사용하기 전에 변수에 값을 부여해야 한다. 앞에서 말했듯이 변수의 성명은 앞당겨졌지만 변수에 값을 부여하는 것은 앞당겨지지 않기 때문에 표현식으로 정의된 함수는 정의하기 전에 호출할 수 없다.다음 코드:
1 person();   /**/
2 function person() {}
3 person();              /* */
1 p();
2 
3 var p = function(){
4 
5 }
6 
7 /*
8  :undefined is not a function  p , 
9 */

함수 호출


(1) 함수로

1 function person(age,name){
2 
3 }
4 
5 person(12," ");   /* */

(2) 방법으로

 1 var calculator = {
 2       operator1 : 1,
 3       operator2 : 2,
 4       add: function(){
 5              this.result = this.operator1 + this.operator2;
 6       }
 7 
 8 };
 9 
10 calculator.add();      // 1+1  
11 calculator.result      =>2
12  
13 /*
14  , calculator , this 
15 */

(3) 구조 함수로

1 var o = new Object();
2 
3 var o = new Obejct;
4 
5 /*
6  , prototype 。 , , this 
7 */

[주] 만약 구조 함수에 형삼이 없다면 자바스크립트 구조 함수 호출의 문법은 실삼 목록과 괄호를 생략할 수 있습니다.그래서 무릇 형삼이 없는 구조 함수 호출은 원괄호를 생략할 수 있다.

(4) 그들의call()과 apply 방법을 통해 간접적으로 호출[뒷말]


this 키워드


this는 키워드입니다. 변수도 속성 이름도 아닙니다.JavaScript 구문에서는 this에 값을 지정할 수 없습니다.변수와 달리 키워드this는 작용역의 제한이 없습니다. 끼워 넣은 함수는 호출된 함수에서this를 계승하지 않습니다.이것에 대해 우리는 실례로 설명한다
 1 var o ={
 2       m: function() {
 3              var self = this;
 4              console.log(this === o);  (1 5              f();
 6             
 7              function() {
 8                      console.log(this === o);  (2 9                      console.log(self == o);     (310              }
11       }
12 }
13 
14 /*
15  (1) true, this o。(2) false, this undined。(3) true,self this 
16 */

종합적으로 알다시피:
(1) 플러그인 함수가 방법으로 호출되면,this의 값은 호출된 대상을 가리킨다.
(2) 플러그인 함수를 함수로 호출하면this값은 전역 대상이 아니라 undefined입니다.
(3) 외부 함수의this 값에 접근하려면this 값을 하나의 변수에 저장해야 합니다. 이 변수와 내부 함수는 모두 하나의 작용역에 있습니다.일반적으로this를 저장하기 위해 변수self를 사용합니다.

명명공간으로서의 함수


끌어들이다


자바스크립트 모듈 코드가 있으면, 이 코드는 다른 자바스크립트 프로그램에 사용될 것이다. (클라이언트 자바스크립트의 경우 일반적으로 다양한 웹 페이지에 사용된다.)만약 이 코드가 중간 계산 결과를 저장하는 변수를 정의했다면.이렇게 하면 문제가 발생한다. 모듈 코드가 다른 프로그램에 놓여 있을 때 이 변수가 이미 만들어졌는지 알 수 없다. 만약 이 변수가 존재한다면 코드와 충돌할 것이다.해결 방법은 코드를 한 함수에 넣고 이 함수를 호출하는 것이다.이렇게 하면 전역 변수는 함수 내의 국부 변수가 된다.익명 함수로 정의합니다. 사용법은 다음과 같습니다.
1 (function(){
//
2 console.log(12) (13 }()); // 4 5 6 7 (function(){ 8 console.log(12); (29 })();

여기에 의문이 아직 해결되지 않았습니다. 만약에 정원우가 알고 있다면 저를 도와 해결해 주셨으면 좋겠습니다. 감사합니다!상기 두 익명 함수의 차이점을 알아차렸는지 모르겠지만, (1)에서 출력한 마지막에 가산점이 없습니다. 만약에 가산점을 넣으면 오류가 발생하여 출력할 수 없습니다. 가산점을 넣지 않으면 정상적으로 출력됩니다. (2)에서 사용하기 쉽습니다!정원우 여러분의 도움을 받아 주셔서 감사합니다.


이런 익명 함수를 정의하고 하나의 표현식에서 바로 호출하는 방법은 매우 흔하다. 예를 들어 코드 검사에서 버그가 발생했는지, 이 버그가 발생하면 패치가 있는 함수의 버전을 되돌려준다! 

함수 속성, 방법


(1)length 속성


length는 할 말이 없다. 가장 중요한 것은 함수에 속하는arguments의 속성이다. 함수 안에서arguments.length는 함수를 전송하는 실참의 개수를 표시하여 함수 재부팅을 시뮬레이션합니다.아래 코드를 보십시오
 1                          function person(age, name, gender, addr) {
 2                              this.age = age;
 3                              this.name = name;
 4                              this.gender = gender;
 5                              this.addr = addr;
 6                                 /* */ 
 7                              switch(arguments.length)
 8                              {
 9                                   case  1:
//
10 break; 11 case 2:
//
12 break; 13 case 3:
//
14 break; 15 case 4:
//
16 break; 17 } 18 } 19 20 var p = new person(1,' '); 21 var p1 = new person(1,' ',false); 22 var p2 = new person(1,' ',false,'hunan'); 23 24

추가:arguments의callee 속성


끌어들이다

1             var factorial = function(x) {
2                 if (x <= 1) return 1;
3                 return x * factorial(x - 1);
4             }
5             console.log(factorial(5));
6                 /* 120*/

상술한 코드는 하나의 수의 계승을 구하기 위해 틀림없이 오류가 없다.지금 약간의 변동을 진행하면 다음과 같다.
1             var factorial = function(x) {
2                 if (x <= 1) return 1;
3                 return x * factorial(x - 1);
4             }
5             var fact2 = factorial;
6             factorial = function() { 7 return 0; 8  } 9 console.log(fact2(5));

상기 명백한fact2 변수는 두 함수를 가리키는데fact2(5)를 호출할 때 첫 번째factorial 함수를 실행하고returnx*factorial(x-1)까지 실행한다.때, 이때 실행되는 것은 두 번째factorial 함수이기 때문에 이때 0을 출력합니다.이것은 우리가 원하는 결과가 아니라는 것이 분명하다. 우리가 필요로 하는 것은 곱하기 바로 실행하는 함수이다. 그 다음은 그 자체가 첫 번째이기 때문에 이때callee () 방법은 자신을 호출하는 데 사용된다.그래서 상술한 코드는 이렇게 수정하면 된다
1             var factorial = function(x) {
2                 if (x <= 1) return 1;
3                 return x * arguments.callee(x - 1);
4             }
5             var fact2 = factorial;
6             factorial = function() { 7 return 0; 8  } 9 console.log(fact2(5));

 
[주]arguments는 또 하나의 비슷한callee의 속성이 있는데 바로caller이다. 엄격한 모드가 아닌 ECMAScript 표준 규범에 의하면callee 속성은 현재 실행 중인 함수를 가리킨다.caller는 비표준적이지만 대부분의 브라우저에서 이 속성을 실현합니다. 이것은 현재 실행 중인 함수의 함수를 가리킵니다.caller 속성을 통해 호출 창고에 접근할 수 있습니다.현재 실행 방법의 주소를 저장하고 오류가 발생하지 않기 때문에callee를 통해 자신을 귀속적으로 호출합니다.

(2)prototype 속성


모든 함수는prototype 속성을 포함하고 이 속성은 하나의 대상의 인용을 가리키며 이 대상을 원형 대상이라고 합니다.모든 함수는 서로 다른 원형 대상을 포함한다.함수를 구조 함수로 사용할 때, 새로 만든 대상은 원형 대상에서 속성을 계승합니다.원형 대상에 관하여 앞에서 이미 말했으니, 원형, 계승 이 강을 참고하시오

(3)call() 및 apply() 방법


이 두 가지 방법은 간접적으로 함수를 호출할 수 있다. 두 가지 방법은 모두 호출에 필요한this의 값을 현식으로 지정할 수 있으며, 모든 함수는 그 대상의 방법으로 호출할 수 있다. 설령 이 함수가 그 대상의 방법이 아니더라도.두 방법 모두 호출된 실삼을 지정할 수 있다.call () 방법은 함수의 실삼으로 자체 실삼 목록을 사용하고, apply () 방법은 수조 형식으로 매개 변수를 전달해야 합니다.ECMAScript5의 엄격한 모드에서call () 과 apply () 의 첫 번째 실삼은this의 값으로 바뀝니다. 전송된 실삼이 원시 값이든null 또는undifined라도.ECMAScript3와 비엄격한 모드에서 전송된null과undefined는 전역 대상으로 대체되고 다른 원시 값은 상응하는 포장 대상으로 대체됩니다.

다음은 코드로 상술한 개념을 해석한다


(1)call() 메서드

 1                 function person(age,name){
 2                     this.age=age;
 3                     this.name=name;
 4                 }
 5    
 6                 var obj=new Object();
 7                 person.call(obj,12,' ');
 8                 console.log(obj.age);
 9                 console.log(obj.name);
10 
11                /*
12                 obj, person call() , obj , obj , this obj, 12 
13                */

(2) apply () 방법


추가 사용법 참고: apply() 상세 정보

(3)bind() 방법


bind()는 ECMAScript5에 추가된 방법이지만 ECMASript3에서 bind()를 쉽게 모의할 수 있습니다. 이름에서 알 수 있듯이 이 방법의 주요 역할은 함수를 특정한 대상에 연결하는 것입니다.
 1 function f(y){
 2        return this.x + y;
 3 }
 4 var o = { x : 1 };
 5 var g =  f.bind(o);
 6 console.log(g(2));
 7 
 8 function bind(f,o){
 9        if(f.bind) return f.bind(o);
10        else return function(){
11               return f.apply(o, arguments);
12        };
13 }

상술한 함수 f를 대상 o에 귀속시키고 함수 f()에서 bind () 방법을 상향 조정하여 대상 o를 매개 변수로 전송하면 이 방법은 새로운 함수를 되돌려줍니다.새로운 함수를 호출하면 원시적인 함수 f()를 o의 방법으로 호출합니다.새 함수를 전송하는 모든 실참은 원시 함수로 전송됩니다.상술한 f.bind(o);이때 함수 f()의this는 o이고 이때this.x=1, 귀속 후 새로운 함수 g를 되돌려주고 함수 g(2)를 호출합니다. 이때 함수 f()는 매개 변수이기 때문에 3을 출력합니다.

함수 전참


(1) 원본 형식 전달(c#의 값 형식)

1                          function person(age){
2                              age++;
3                          }
4                          var age = 12;
5                          person(age);
6                          console.log(age);

상술한 코드에 근거하여 당신은 얼마나 인쇄될 것이라고 생각합니까?우리는 한마디씩 분석한다.

 (1)var age = 12;창고에 공간 주소를 0x1로 가정합니다. 이 때 0x1은 변수age이고 값은 12입니다.


 (2)person(age);함수person을 호출하여 실삼을 전송합니다. 이때person의 형삼은 국부 변수에 해당하기 때문에 창고에 공간 주소는 0x2이고 변수는age입니다. 상기(1)의 값을 (2)의 age에 부여합니다. 그래서 같은 12입니다. 그리고 함수체에 들어가서 age++를 추가합니다. 이때 새로 만든 국부 변수의 값은 바뀌지 않았습니다. (1)의 age 값은 바뀌지 않았습니다.


(3) 12를 인쇄합니다.


(2) 객체 전달 (이른바 c#의 참조 유형)

1                          function person(p){
2                                 p.age++;
3                          }
4                          var p = { age : 12 };
5                          person(p);
6                          console.log(p.age);

같은 이치로 분석하다

(1) var p = { age : 12 };먼저 창고에 공간 주소가 0x1 값이null인 것을 개척한 다음에 오른쪽에 공간 주소가 0x2인 빈 대상을 먼저 개척한 다음에 속성age를 정의하고 그 값이 12이며 이 대상이 변수 p를 가리키기 때문에 이때 변수의 값은 0x2이다.


(2)person(p);같은 p는 이때person류의 국부 변수에 해당한다. 먼저 창고에 공간 주소가 ox3이고 이름이 p인 변수를 개척한다. 이때 (1)에서 p의 저장 값 0x2를 0x3에서 p의 값에 부여한다. 그래서 이때 0x3의 값은 0x2이다. 즉, 이때 ox2는 그 주소가 0x2이고 속성이age값이 12인 대상을 가리킨다.그리고 함수체 내부에 들어가 나이에 대해age++를 진행하면 대상이 쌓인 속성age는 13이 됩니다.


(3) 요약하면 인쇄된 P의 age는 13입니다.


총결산 전삼


원본 유형(값 유형)을 전달하든 대상(인용 유형)을 전달하든 창고에 있는 변수의 값이 저장된 값이든 주소만 보면 된다. 만약에 저장된 값이 값이라면 복사본을 복사해도 원래의 값이 바뀌지 않고 변수의 값이 저장된 것이 주소라면 함수체에서 값을 바꾸면 원래의 대상의 값도 영향을 받는다.


좋은 웹페이지 즐겨찾기