1. 함수 호출
함수는 확실히 JavaScript에서 가장 중요한 것입니다. JavaScript에서 Function은 프로시저, 메소드, 생성자, 클래스 및 모듈의 기능을 가정합니다.
객체 지향 프로그래밍에서 함수, 메서드 및 클래스 생성자는 서로 다른 구문으로 구현되는 세 가지 다른 요소인 경우가 많습니다. 그러나 JavaScript에서는 이 세 가지 개념이 세 가지 다른 모드를 통해 함수로 구현됩니다.
가장 간단한 사용 모드는 함수 호출입니다.
function hello(username) { return "hello, " + username; } hello("Keyser Söze"); // "hello, Keyser Söze"
2. 메소드 호출
JavaScript에서 메소드의 개념은 객체의 속성이 함수라는 것입니다. 동일한 함수이지만 객체의 멤버에 할당한 후에는 다릅니다. 객체의 멤버에 함수를 할당한 후에는 더 이상 함수가 아니라 메서드라고 합니다.
var obj = { hello: function() { return "hello, " + this.username; }, username: "Hans Gruber" }; obj.hello(); // "hello, Hans Gruber"
실제 동작은 호출 자체가 이것이 바인딩될 개체를 결정한다는 것입니다. 즉,
obj1.hello()는 이것을 obj1에 바인딩하고, obj2.hello()는 이것을 obj2에 바인딩합니다. 한 문장만 기억하세요. 누가 전화하든 누구를 가리킬 것입니다.
이 바인딩 규칙으로 인해 다음과 같은 사용법도 가능합니다.
function hello() { return "hello, " + this.username; } var obj1 = { hello: hello, username: "Gordon Gekko" }; obj1.hello(); // "hello, Gordon Gekko" var obj2 = { hello: hello, username: "Biff Tannen" };_ obj2.hello(); // "hello, Biff Tannen"
그러나 위의 hello 함수와 같은 일반적인 함수에서는 this 키워드를 직접 호출하는 경우에는 this를 가리키는 것이 문제가 됩니다. 이 경우 일반적으로 브라우저의 창 개체인 전역 개체(GlobalObject)를 가리키는 경우가 많습니다.
그리고 이 행동은 불확실하고 의미가 없습니다.
따라서 ES5 표준에서는 엄격 모드를 사용하면 정의되지 않음으로 설정됩니다.
function hello() { "use strict"; return "hello, " + this.username; } hello(); // error: cannot read property "username" of undefined
위의 접근 방식은 잠재적인 오류를 더 빨리 노출하고 오작동과 찾기 어려운 버그를 방지하는 것입니다.
일반적인 함수 호출과 메서드 호출의 차이점은 이 예제를 보면 명확해집니다.
var func = function() { alert(this); }; var o = {}; o.fn = func; // 比较 alert(o.fn === func);//true // 调用 func();//[object Window] o.fn();//[object Object]
여기서 실행한 결과는 두 기능이 동일하므로 인쇄된 결과가 true입니다. 그러나 두 함수의 호출이 다르기 때문에 func를 호출하면 [object Window]가 인쇄되고, o.fn의 인쇄 결과는 [object Object]가 됩니다.
함수 호출과 메서드 호출의 차이점은 다음과 같습니다. 함수 호출에서 this는 구체적으로 전역 개체 창을 참조하는 반면, 메서드에서는 구체적으로 현재 개체를 참조합니다. 즉, o.fn의 this는 개체를 참조합니다. 영형.
3. 생성자 호출
함수의 세 번째 사용 모드는 생성자로 사용하는 것입니다.
생성자의이것
이 의미를 알기 위해서는 객체 생성 과정을 분석해야 합니다.
var Person = function() { this.name = "小平果"; }; var p = new Person();
여기서 Person 함수를 먼저 정의합니다. 전체 실행을 분석해 보겠습니다.
생성자의 실행을 분석해 보면 생성자에 있는 이것이 현재 객체라는 것을 알 수 있습니다.
생성자 반환
생성자에서 반환의 의미가 변경되었습니다. 먼저 생성자에서 객체가 반환되면 반환이 숫자, 부울 및 객체가 아닌 경우 원래 의미가 유지됩니다. 문자열인 경우 반환은 이것이고, 반환 문이 없으면 다음 코드도 반환됩니다.
// 返回一个对象的 return var ctr = function() { this.name = "赵晓虎"; return { name:"牛亮亮" }; }; // 创建对象 var p = new ctr(); // 访问name属性 alert(p.name); //执行代码,这里打印的结果是"牛亮亮". 因为构造方法中返回的是一个对象,那么保留return的意义,返回内容为return后面的对象. 再看下面代码: // 定义返回非对象数据的构造器 var ctr = function() { this.name = "赵晓虎"; return "牛亮亮"; }; // 创建对象 var p = new ctr(); // 使用 alert(p); alert(p.name);
코드를 실행한 결과 팝업창에는 먼저 [object Object]가 출력된 후 "Zhao Xiaohu"가 출력됩니다. 왜냐하면 여기서 return은 기본 유형에 속하는 문자열이기 때문입니다. 여기서는 유효하지 않으며 this 개체가 반환됩니다. 따라서 첫 번째는 [object Object]를 인쇄하지만 두 번째는 undefine을 인쇄하지 않습니다.
function User(name, passwordHash) { this.name = name; this.passwordHash = passwordHash; } var u = new User("sfalken", "0ef33ae791068ec64b502d6cb0191387"); u.name; // "sfalken"
새 키를 사용하여 함수를 생성자로 호출합니다. 함수 및 메소드 호출과 달리 생성자는 새 객체를 전달하고 여기에 바인딩한 다음 객체를 생성자의 반환 값으로 반환합니다. 생성자 함수 자체의 기능은 객체를 초기화하는 것입니다.
생성자 호출 시 흔히 발생하는 실수
다음 생성자를 행복하게 정의했습니다.
var Coder = function( nick ){ this.nick = nick; };
생성자를 정의한 후에는 어떻게 되나요? 맞습니다. 빠르게 인스턴스화하세요.
var coder = Coder( 'casper' );
이 코더 형제의 이름은 무엇입니까? 빠르게 인쇄하세요:
console.log( coder.nick ); //undefined = =b 竟然是undefined!!再回过头看看实例化的那个语句,不难发现问题出在哪里:少了个new var coder = Coder( 'casper' ); //当作普通的函数来调用,故内部的this指针其实指向window对象 console.log( window.nick); //输出:casper var coder = new Coder( 'casper' ); //加上new,一切皆不同,this正确地指向了当前创建的实例 console.log( coder.nick ); //输出:casper
这样的错误貌似挺低级的,但出现的概率挺高的,肿么去避免或减少这种情况的发生呢?
可以在内部实现里面动下手脚:
var Coder = function( nick ){ if( !(this instanceof Coder) ){ return new Coder( nick ); } this.nick = nick; };
其实很简单,实例化的时候,内部判断下,当前this指向的对象的类型即可,如果非当前构造函数的类型,强制重新调用一遍构造函数。
突然觉得Coder这名字不够洋气?想用Hacker,好吧,我改。。。数了下,一共有三处要改,这不科学,有没有办法只把构造函数的名字改了就行?
当然有:
var Coder = function( nick ){ if( !(this instanceof arguments.callee) ){ return new arguments.callee( nick ); } this.nick = nick; };
tips:据说在ES 5的严格模式下面arguments.callee会被禁用,不过仅当ES 5普及同时你指定了要使用严格模式,否则还是可以用的发散下思维。
以上就是本文的全部内容,希望对大家学习函数调用、方法调用和构造函数调用有所帮助。