코드 복사 코드는 다음과 같습니다.
/****************** 객체지향 ******************/
/********** 1: 객체 생성, 프로토타입 체인 **********/
/* 객체를 생성하기 위해서는 생성자(클래스 메소드)에 대해 논의하고 그 내용을 심도 있게 이해하는 것이 중요합니다
*/
function MyFunc() { }; //빈 함수 정의
var anObj = new MyFunc() //new 연산자를 사용하고 MyFun 함수를 사용하여 객체 생성
/ /동일함:
function MyFunc() { };
var anObj = {}; //객체 생성
anObj.__proto__ = MyFunc.call(anObj) /anObj 객체를 이 포인터로 사용하여 MyFunc 함수를 호출합니다.
/*
var anObject = new aFunction() 형식의 객체를 생성하는 프로세스는 실제로 세 단계로 나눌 수 있습니다.
1단계 : 새 개체(anObject)를 만듭니다.
2단계: 개체의 내장 프로토타입 개체(__proto__)를 생성자 프로토타입에서 참조하는 프로토타입 개체로 설정합니다.
3단계: 개체를 사용하여 생성자를 호출합니다. 매개변수, 멤버 설정 등 초기화 작업을 완료합니다.
객체가 생성된 후 객체에 대한 모든 액세스 및 작업은 객체 자체 및 프로토타입 체인의 객체 문자열에만 관련됩니다.
생성자와는 아무런 관련이 없습니다.
즉, 생성자는 객체 생성 시 프로토타입 객체를 도입하고 객체를 초기화하는 역할만 합니다.
프로토타입 체인: (참조: http://hi.baidu.com/fegro/blog/item/41ec7ca70cdb98e59152eed0.html)
각 객체(여기서의 객체는 중괄호 안에 있는 객체만 참조해야 하며, 함수, 배열 포함? )
는 __proto__라는 속성을 초기화합니다. 객체의 속성에 액세스하면
이 속성이 객체 내부에 존재하지 않으면 검색됩니다. __proto__의 이 속성,
이 __proto__에는 자체 __proto__가 있으므로 계속해서 이를 찾는데, 이것이 바로 우리가 일반적으로 프로토타입 체인의 개념이라고 부르는 것입니다.
*/
/* 객체 생성 원리를 이해한 후 아래 두 예제의 결과를 분석해 볼 수 있습니다*/
var yx01 = new function() {return "Circle Center"};
alert (yx01); // [객체 객체]
var yx02 = new function() {return new String("center of Circle")}
alert(yx02); Circle"
/* 설명 :
"Circle Center"는 기본 문자열 타입이고, new String("Circle Center")은 문자열 객체를 생성합니다.
new 표현식 뒤의 생성자가 참조 객체(배열, 객체, 함수 등)를 반환하는 한, new로 생성된 객체를 덮어씁니다.
기본 유형을 반환하는 경우(해당 항목이 없는 경우) 반환하면 실제로는 기본 유형인 정의되지 않은 값을 반환합니다.
그런 다음 new로 생성된 객체를 반환합니다.
참고: http://www.planabc.net/2008/02/20/javascript_new_function/
*/
/********** 2: 데이터 유형 감지 **********/
/* 데이터 유형 판단 방법:
constructor, typeof, instanceof, Object.prototype.toString.call()
*/
/***** 1. 생성자 속성을 통해 *****/
var myvar= new Array(" a"," b","c","d");
함수 A(){}
myvar.constructor = A;
var c = myvar.constructor;
alert(c ); // function A(){}
//생성자 속성을 통해 유형을 얻는 방법은 쉽게 수정될 수 있으므로 유형을 결정하는 데 사용해서는 안 된다는 것을 알 수 있습니다.
/***** 2. typeof를 통해 *****/
/*
typeof는 함수가 아니라 연산자입니다.
typeof의 실제 적용은 객체가 정의되었거나 값이 할당되었는지 여부를 감지하는 것입니다.
예를 들어 if(typeof a!="undefine"){}인 경우 if(a)를 사용하지 마세요. a가 존재하지 않으면(선언되지 않음) 오류가 발생하기 때문입니다.
typeof가 객체 유형을 감지하면 일반적으로
number, boolean, string, function, object, unundefined 결과만 반환할 수 있습니다.
배열, Null, 사용자 정의 개체 등에 typeof를 사용하면 항상 개체가 반환됩니다.
이것이 typeof의 제한 사항입니다.
*/
var num = new Number(1);
var arr = [1,2,3]
alert(typeof num)
alert (typeof arr); //배열 대신 객체
alert(typeof null); // object
/***** 3. 인스턴스 오브를 통해 *****/
/* 객체가 객체인지 확인하려면 objectof 연산자를 사용하세요. 클래스의 인스턴스.
obj instanceof Class가 true를 반환하면 Class의 프로토타입은 obj 프로토타입 체인의 프로토타입과 동일한 객체입니다.
즉, obj는 Class 또는 Class의 하위 클래스에 의해 생성됩니다.
*/
function t(){};
t.prototype = Array.prototype;
//t.prototype = []
var x = new
alert(x 인스턴스of t);//pop true
alert(x 인스턴스of Array);//pop true
alert(x 인스턴스of Object);//pop true
/*
by instanceof를 통해 데이터 유형을 판단하는 것도 신뢰할 수 없음을 알 수 있습니다.
객체(여기서 x)의 프로토타입 체인은 매우 길 수 있으므로 각 프로토타입의 유형이 다를 수 있습니다.
또한 iframe 내에서는 오류가 발생하기 쉽습니다.
즉, 배열 a를 정의하는 페이지가 있고 해당 페이지에 배열의 top.a 인스턴스가 중첩되어 있습니다. Iframe에 전달되면 false를 반환합니다.
이 설명은 상위 페이지와 포함된 iframe의 개체가 다르며 함께 혼합될 수 없음을 나타냅니다.
top.a 인스턴스로 변경됨 top.Array는 true를 반환합니다.
*/
/***** 4. Object.prototype.toString.call()을 통해 *****/
/*
Object.prototype.toString.call() 함수 It is:
1. 객체의 클래스 이름(객체 유형)을 가져옵니다.
2. 그런 다음 [객체, 획득한 클래스 이름]을 결합하여 반환합니다.
배열, 날짜, 함수 및 기타 유형의 객체를 결정하는 데 사용할 수 있습니다.
*/
var num = new Number(1)
var arr = [1,2,3]; 🎜> Alert(Object.prototype.toString.call(num)); // [객체 번호]
alert(Object.prototype.toString.call(arr)) // [객체 배열]
// 확장된 예: (적용은 호출과 동일)
window.utils = {
toString: Object.prototype.toString,
isObject: function (obj) {
return this.toString.apply(obj ) == '[객체 객체]';
},
isFunction: function (obj) {
return this.toString.apply(obj) === '[객체 함수]'
} ,
isArray: function (obj) {
return this.toString.apply(obj) === '[object Array]'
}
}
function A() { }
window.utils.isFunction(A); //true
window.utils.isObject(new A()) //true
window.utils.isArray([]); true
/*
jQuery와 같은 프레임워크에서는 이 방법을 사용하여 객체의 유형을 결정하므로 이 방법을 권위 있는 판단 방법으로 사용할 수 있습니다.
그러나 Object.prototype.toString 메서드를 재정의하면 이를 사용하여 데이터 유형을 결정할 때 오류가 발생할 수 있습니다.
따라서 일반적으로 Object.prototype.toString 메서드를 재정의하지 마십시오.
*/
/********** 3: 상속 **********/
/*
JS 상속은 클로저와 마찬가지로 JS를 깊이 배우고 싶어하는 거의 모든 친구들이 의논해야 하는 문제이므로 매우 다양합니다. 모든 관련 정보를 이용할 수 있습니다.
JS 상속 코드에는 여러 버전이 있지만 원칙은 동일하며 핵심은 프로토타입 객체를 사용합니다.
다른 객체 지향 언어의 스타일과 유사하기 위해 대부분 "클래스" 스타일 시뮬레이션을 사용합니다.
상속의 자세한 원리는 인터넷에 너무 많아서 자세히 설명하지 않습니다.
다음은 Jquery 작성자 John Resig가 작성한 상속의 예입니다.
(자세한 댓글은 블로그에서 퍼온 글인데, 누가 만들었는지 몰라서 여기에 비공개로 다시 올립니다)
*/
(function () {
// 초기화 변수를 사용함 현재를 표시하기 위해 클래스 생성 단계인지
// - 클래스 생성 단계에서는 init 프로토타입 메소드를 호출할 수 없습니다
// - 이 문제에 대해서는 3번째에서 자세히 설명했습니다. 이 시리즈의 기사
// fnTest는 정규식이며 가능한 값은 (/b_superb/ 또는 /.*/)입니다.
// - /xyz/.test(function()의 테스트 { xyz; })는 테스트 매개변수가 함수인 경우를 브라우저에서 지원합니까?
// - 그런데 IE7.0, Chrome2.0, FF3.5를 테스트했는데 이 테스트가 모두 true를 반환했습니다.
// - 따라서 fnTest에 값을 할당하는 것은 대부분의 경우에 적합합니다. fnTest = /b_superb/;
var 초기화 = false, fnTest = /xyz/.test(function () { xyz; }) ? /b_superb/ : /.*/ ;
// 기본 클래스 생성자
// 이것은 창이므로 이 전체 코드는 외부 세계에 대한 창을 엽니다. window.Class
이것입니다. Class = function () { } ;
// 상속된 메서드 정의
Class.extend = function (prop) {
// 이 부분은 매우 혼란스럽습니다. 이 시리즈의 두 번째 기사에서 언급한 내용을 기억하세요.
// - 이것이 구체적으로 무엇을 가리키는지 정의할 때 결정할 수 없지만 이 함수가 어떻게 호출되는지에 따라 다릅니다.
// - 우리는 이미 확장이 생성자가 아닌 메서드로 호출되어야 한다는 것을 알고 있습니다.
// - 여기서 이것은 객체가 아니라 함수(예: 클래스)를 가리킵니다. 그러면 this.prototype은 상위 클래스의 프로토타입 객체입니다.
// - 참고: _super는 클래스의 프로토타입 객체를 가리킵니다. 상위 클래스인 경우 다음 코드에서 이 변수를 여러 번 만나게 됩니다.
var _super = this.prototype;
// 하위 클래스의 프로토타입을 상위 클래스의 인스턴스 객체로 지정하면 상속이 완료됩니다.
// - 참고: this는 기본 클래스 생성자입니다(예: 클래스)
initializing = true;
var 프로토타입 = new this()
initializing = false; 코드는 작성자가 최적화했기 때문에 매우 직설적으로 읽혀지므로 나중에 자세히 설명하겠습니다.
for (var name in prop) {
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name ] == "function" && fnTest.test(prop[name]) ?
(function (name, fn) {
return function () {
var tmp = this._super; // here is 필요한 경우 91행의 주석 코드로 설명할 수 있습니다.
this._super[이름];
var ret = fn.apply(this, 인수);
this._super =
return ret; })(name, prop[name]):
prop[name];
}
// Resig가 변장을 매우 잘한다는 것을 여기서 알 수 있습니다.
// - 같은 이름의 변수를 전역변수로 덮어씌우려면 헷갈리죠
// - 발음이 어색하다면 function Class() 대신 function F() 같은 다른 이름을 사용해도 됩니다
// - 참고: 여기서 클래스는 가장 바깥쪽 레이어에 정의된 기본 클래스 생성자가 아닙니다
// 여기의 클래스는 위의 window.Class 함수와 다릅니다. 다음은 window.Class
함수 내부의 함수 로컬 변수입니다. Class() {
// 클래스를 인스턴스화할 때 프로토타입 메서드 init를 호출합니다.
if (!initializing && this.init)
this.init.apply(this, 인수)
}
// 하위 클래스의 프로토타입은 상위 클래스의 인스턴스를 가리킵니다(상속을 완료하는 열쇠)
Class.prototype = 프로토타입; // 클래스는 초기 window.Class가 아닌 위의 클래스를 참조합니다.
// 생성자 포인팅 오류 수정
// Class.prototype.constructor = Class;를 사용하여 수정할 수 있나요? ? ?
Class.constructor = Class;
// 하위 클래스는 자동으로 확장 메소드를 획득하고,args.callee는 현재 실행 중인 함수를 가리킵니다.
Class.extend =
return Class; > };
})();