JavaScript 상속에 대한 자세한 설명(2)_js 객체지향

WBOY
풀어 주다: 2016-05-16 18:50:04
원래의
881명이 탐색했습니다.

이것

현재 개체를 나타냅니다. 전역 범위에서 사용되는 경우 현재 페이지 개체 창을 참조하고, 함수에서 사용되는 경우 참조하는 것은 이 함수가 호출되는 개체에 따라 결정됩니다. 런타임에. 또한 함수에서 this의 특정 포인터를 변경하기 위해 apply와 call이라는 두 가지 전역 메서드를 사용할 수도 있습니다.

먼저 전역 범위에서 이를 사용하는 예를 살펴보겠습니다.

  <script type="text/javascript">
   console.log(this === window); // true
   console.log(window.alert === this.alert); // true
   console.log(this.parseInt("021", 10)); // 10
  </script>
  
로그인 후 복사

함수에서 이는 다음과 같이 함수가 정의될 ​​때가 아니라 런타임에 결정됩니다.

  // 定义一个全局函数
  function foo() {
   console.log(this.fruit);
  }
  // 定义一个全局变量,等价于window.fruit = "apple";
  var fruit = "apple";
  // 此时函数foo中this指向window对象
  // 这种调用方式和window.foo();是完全等价的
  foo(); // "apple"

  // 自定义一个对象,并将此对象的属性foo指向全局函数foo
  var pack = {
   fruit: "orange",
   foo: foo
  };
  // 此时函数foo中this指向window.pack对象
  pack.foo(); // "orange"
  
로그인 후 복사

전역 함수 apply 및 call을 사용하여 함수에서 this의 포인터를 다음과 같이 변경할 수 있습니다.

  // 定义一个全局函数
  function foo() {
   console.log(this.fruit);
  }
  
  // 定义一个全局变量
  var fruit = "apple";
  // 自定义一个对象
  var pack = {
   fruit: "orange"
  };
  
  // 等价于window.foo();
  foo.apply(window); // "apple"
  // 此时foo中的this === pack
  foo.apply(pack); // "orange"
  
로그인 후 복사
참고: 두 함수 apply 및 call은 동일한 함수를 갖는다는 점만 다릅니다. 두 함수의 매개변수 정의가 다릅니다.

함수도 JavaScript의 객체이기 때문에 다음과 같은 흥미로운 예를 볼 수 있습니다.

  // 定义一个全局函数
  function foo() {
   if (this === window) {
    console.log("this is window.");
   }
  }
  
  // 函数foo也是对象,所以可以定义foo的属性boo为一个函数
  foo.boo = function() {
   if (this === foo) {
    console.log("this is foo.");
   } else if (this === window) {
    console.log("this is window.");
   }
  };
  // 等价于window.foo();
  foo(); // this is window.
  
  // 可以看到函数中this的指向调用函数的对象
  foo.boo(); // this is foo.
  
  // 使用apply改变函数中this的指向
  foo.boo.apply(window); // this is window.
  
로그인 후 복사

시제품

우리는 이미 프로토타입을 사용하여 1장에서 클래스 구현과 상속을 시뮬레이션했습니다. 프로토타입은 기본적으로 JavaScript 객체입니다. 그리고 모든 함수에는 기본 프로토타입 속성이 있습니다.
사용자 정의 개체를 생성하는 시나리오에서 이 함수를 사용하는 경우 이 함수를 생성자라고 부릅니다. 예를 들어 다음은 간단한 시나리오입니다.

  // 构造函数
  function Person(name) {
   this.name = name;
  }
  // 定义Person的原型,原型中的属性可以被自定义对象引用
  Person.prototype = {
   getName: function() {
    return this.name;
   }
  }
  var zhang = new Person("ZhangSan");
  console.log(zhang.getName()); // "ZhangSan"
  
로그인 후 복사
비유적으로 JavaScript의 데이터 유형(문자열, 숫자, 배열, 개체, 날짜)을 고려해 보겠습니다. 이러한 유형은 다음과 같이 JavaScript의 생성자로 구현된다고 믿을 만한 이유가 있습니다.
  // 定义数组的构造函数,作为JavaScript的一种预定义类型
  function Array() {
   // ...
  }
  
  // 初始化数组的实例
  var arr1 = new Array(1, 56, 34, 12);
  // 但是,我们更倾向于如下的语法定义:
  var arr2 = [1, 56, 34, 12];
  
로그인 후 복사
동시에 배열에서 작동하는 여러 메서드(예: concat, Join, push)도 프로토타입 속성에 정의되어야 합니다.
사실 JavaScript의 모든 내장 데이터 유형에는 읽기 전용 프로토타입 속성이 있지만(이해할 수 있습니다. 이러한 유형의 프로토타입 속성이 수정되면 사전 정의된 메소드가 사라지기 때문입니다), 여기에 자신만의 확장 메소드를 추가할 수 있습니다. .
  // 向JavaScript固有类型Array扩展一个获取最小值的方法
  Array.prototype.min = function() {
   var min = this[0];
   for (var i = 1; i < this.length; i++) {
    if (this[i] < min) {
     min = this[i];
    }
   }
   return min;
  };
  
  // 在任意Array的实例上调用min方法
  console.log([1, 56, 34, 12].min()); // 1
  
로그인 후 복사

참고: 여기에 함정이 있습니다. 배열의 프로토타입에 확장 메서드를 추가한 후 for-in을 사용하여 배열을 반복할 때 이 확장 메서드도 반복됩니다.
다음 코드는 이를 보여줍니다(min 메소드가 Array 프로토타입으로 확장되었다고 가정).
  var arr = [1, 56, 34, 12];
  var total = 0;
  for (var i in arr) {
   total += parseInt(arr[i], 10);
  }
  console.log(total); // NaN
  
  
로그인 후 복사
해결책도 매우 간단합니다.
  var arr = [1, 56, 34, 12];
  var total = 0;
  for (var i in arr) {
   if (arr.hasOwnProperty(i)) {
    total += parseInt(arr[i], 10);
   }
  }
  console.log(total); // 103
  
로그인 후 복사

생성자

생성자는 항상 현재 객체를 생성한 생성자를 가리킵니다. 예:

  // 等价于 var foo = new Array(1, 56, 34, 12);
  var arr = [1, 56, 34, 12];
  console.log(arr.constructor === Array); // true
  // 等价于 var foo = new Function();
  var Foo = function() { };
  console.log(Foo.constructor === Function); // true
  // 由构造函数实例化一个obj对象
  var obj = new Foo();
  console.log(obj.constructor === Foo); // true
  
  // 将上面两段代码合起来,就得到下面的结论
  console.log(obj.constructor.constructor === Function); // true
  
로그인 후 복사

그러나 생성자가 프로토타입을 만나면 흥미로운 일이 발생합니다.
각 함수에는 기본 속성 프로토타입이 있고 이 프로토타입의 생성자는 기본적으로 이 함수를 가리킨다는 것을 알고 있습니다. 다음 예와 같이

  function Person(name) {
   this.name = name;
  };
  Person.prototype.getName = function() {
   return this.name;
  };
  var p = new Person("ZhangSan");
  
  console.log(p.constructor === Person); // true
  console.log(Person.prototype.constructor === Person); // true
  // 将上两行代码合并就得到如下结果
  console.log(p.constructor.prototype.constructor === Person); // true
  
로그인 후 복사
함수의 프로토타입을 재정의할 때(참고: 위 예와의 차이점은 수정이 아니라 재정의임) 생성자의 동작이 약간 이상했습니다. , 다음 예와 같이:
  function Person(name) {
   this.name = name;
  };
  Person.prototype = {
   getName: function() {
    return this.name;
   }
  };
  var p = new Person("ZhangSan");
  console.log(p.constructor === Person); // false
  console.log(Person.prototype.constructor === Person); // false
  console.log(p.constructor.prototype.constructor === Person); // false
  
로그인 후 복사
Why?
Person.prototype을 덮어쓸 때 다음 코드 연산과 동일하다는 것이 밝혀졌습니다.
  Person.prototype = new Object({
   getName: function() {
    return this.name;
   }
  });
  
로그인 후 복사
그리고 생성자는 항상 자신을 생성하는 생성자를 가리키므로 이때 Person.prototype.constructor === Object , 즉:
  function Person(name) {
   this.name = name;
  };
  Person.prototype = {
   getName: function() {
    return this.name;
   }
  };
  var p = new Person("ZhangSan");
  console.log(p.constructor === Object); // true
  console.log(Person.prototype.constructor === Object); // true
  console.log(p.constructor.prototype.constructor === Object); // true
  
로그인 후 복사
이 문제를 해결하는 방법은 무엇입니까? 이 방법도 매우 간단합니다. Person.prototype.constructor를 재정의하세요.
  function Person(name) {
   this.name = name;
  };
  Person.prototype = new Object({
   getName: function() {
    return this.name;
   }
  });
  Person.prototype.constructor = Person;
  var p = new Person("ZhangSan");
  console.log(p.constructor === Person); // true
  console.log(Person.prototype.constructor === Person); // true
  console.log(p.constructor.prototype.constructor === Person); // true
  
로그인 후 복사


다음 장에서는 첫 번째 장에서 언급한 Person-Employee 클래스 구현과 상속을 개선할 것입니다.

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!