>  기사  >  웹 프론트엔드  >  JavaScript의 객체지향적 사고 소개

JavaScript의 객체지향적 사고 소개

黄舟
黄舟원래의
2017-08-22 11:07:36971검색

아래 편집기에서 JavaScript의 객체 지향적 사고에 대한 기사를 가져올 수 있습니다. 편집자님이 꽤 좋다고 생각하셔서 지금 공유하고 모두에게 참고용으로 드리도록 하겠습니다. 에디터를 따라가서 살펴봅시다

객체지향의 세 가지 기본 특성

캡슐화(관련 정보(데이터든 메소드든)를 객체에 저장하는 능력)

상속(타인에 의한) 클래스(또는 여러 클래스) 클래스의 속성과 메서드를 얻는 기능

다형성(다양한 상황에서 개체의 여러 형태)

클래스 또는 개체 정의

첫 번째 유형: 객체 객체 기반


var person = new Object();
person.name = "Rose";
person.age = 18;
person.getName = function () {
 return this.name;
};
console.log(person.name);//Rose
console.log(person.getName);//function () {return this.name;}
console.log(person.getName());//Rose

단점: 여러 객체를 생성할 수 없습니다.

두 번째: 리터럴 메서드 기반


var person = {
 name : "Rose",
 age : 18 ,
 getName : function () {
  return this.name;
 }
};
console.log(person.name);//Rose
console.log(person.getName);//function () {return this.name;}
console.log(person.getName());//Rose

장점: 개체에 포함된 속성과 메서드를 찾는 것이 비교적 명확합니다.

단점: 여러 개체를 만들 수 없습니다.

세 번째: 공장 모드

방법 1:


function createPerson(name,age) {
 var object = new Object();
 object.name = name;
 object.age = age;
 object.getName = function () {
  return this.name;
 };
 return object;
}
var person1 = createPerson("Rose",18);
var person2 = createPerson("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//false//重复生成函数,为每个对象都创建独立的函数版本

장점: 여러 개체를 생성할 수 있습니다.

단점: 각 개체에 대해 getName() 함수를 반복 생성합니다. .

방법 2:


function createPerson(name,age) {
 var object = new Object();
 object.name = name;
 object.age = age;
 object.getName = getName;
 return object;
}
function getName() {
 return this.name;
}
var person1 = createPerson("Rose",18);
var person2 = createPerson("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享同一个函数

장점: 여러 개체를 만들 수 있습니다.

단점: 의미상 getName() 함수는 Person 개체의 메서드와 별로 유사하지 않으며 인식도 그렇지 않습니다. 높은.

네 번째: 생성자 메서드

방법 1:


function Person(name,age) {
 this.name = name;
 this.age = age;
 this.getName = function () {
  return this.name;
 }
}
var person1 = new Person("Rose",18);
var person2 = new Person("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName); //false//重复生成函数,为每个对象都创建独立的函数版本

장점: 여러 개체를 생성할 수 있습니다.

단점: 각 개체에 대해 getName() 함수를 반복적으로 생성합니다. .

방법 2:


function Person(name,age) {
 this.name = name;
 this.age = age;
 this.getName = getName ;
}
function getName() {
 return this.name;
}
var person1 = new Person("Rose",18);
var person2 = new Person("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName); //true//共享同一个函数

장점: 여러 개체를 만들 수 있습니다.

단점: 의미상 getName() 함수는 Person 개체의 메서드와 별로 유사하지 않으며 인식도 그렇지 않습니다. 높은.

다섯 번째 방법: 프로토타입 방법


function Person() {
}
Person.prototype.name = 'Rose';
Person.prototype.age = 18;
Person.prototype.getName = function () {
 return this.name;
};
var person1 = new Person();
var person2 = new Person();
console.log(person1.name);//Rose
console.log(person2.name);//Rose//共享同一个属性
console.log(person1.getName === person2.getName);//true//共享同一个函数

단점: 생성자의 초기화 매개변수 전달이 생략되어 특정 프로그램에 불편을 초래합니다. 또한 가장 중요한 것은 객체의 속성이 언제인지입니다. 참조 유형이며 해당 값은 변경되지 않으며 항상 동일한 외부 개체를 참조합니다. 모든 인스턴스의 개체에 대한 모든 작업은 다른 인스턴스에 영향을 미칩니다.


function Person() {
}
Person.prototype.name = 'Rose';
Person.prototype.age = 18;
Person.prototype.lessons = ["语文","数学"];
Person.prototype.getName = function () {
 return this.name;
};
var person1 = new Person();
person1.lessons.push("英语");
var person2 = new Person();
console.log(person1.lessons);//["语文", "数学", "英语"]
console.log(person2.lessons);//["语文", "数学", "英语"]//person1修改影响了person2

여섯 번째: 생성자 + 프로토타입 메서드(권장)


function Person(name,age) {
 this.name = name;
 this.age = age;
}
Person.prototype.getName = function () {
 return this.name;
};
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定义的方法

단점: 속성은 생성자 내에서 정의되고 메서드는 생성자 외부에서 정의되므로 객체 지향 캡슐화 아이디어와 일치하지 않습니다.

7번째 방법: 생성자 + 동적 프로토타입 방법(권장)

방법 1:


function Person(name,age) {
 this.name = name;
 this.age = age;
 if (typeof Person._getName === "undefined"){
  Person.prototype.getName = function () {
   return this.name;
  };
  Person._getName = true;
 }
}
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定义的方法

방법 2:


function Person(name,age) {
 this.name = name;
 this.age = age;
 if (typeof this.getName !== "function"){
  Person.prototype.getName = function () {
   return this.name;
  };
 }
}
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定义的方法

객체 확장 및 삭제 속성

Javascript 객체는 '.' 연산자를 사용하여 해당 속성을 동적으로 확장할 수 있습니다. 속성은 'delete' 키워드를 사용하거나 속성 값을 'undefine'으로 설정하여 삭제할 수 있습니다.


function Person(name,age) {
 this.name = name;
 this.age = age;
 if (typeof Person._getName === "undefined"){
  Person.prototype.getName = function () {
   return this.name;
  };
  Person._getName = true;
 }
}
var person = new Person("Rose",18);
person.job = 'Engineer';//添加属性
console.log(person.job);//Engineer
delete person.job;//删除属性
console.log(person.job);//undefined//删除属性后值为undefined
person.age = undefined;//删除属性
console.log(person.age);//undefined//删除属性后值为undefined

객체 속성 유형

Data attribute

Features:

[configurable]: 삭제 연산자를 사용하여 삭제 및 재정의할 수 있는지 또는 접근자 속성으로 수정할 수 있는지 여부를 나타냅니다. . 기본값은 true입니다.

[enumberable]: for-in 루프를 통해 속성을 반환할 수 있는지 여부를 나타냅니다. 기본값 true;

[writable]: 속성 값을 수정할 수 있는지 여부를 나타냅니다. 기본값 true;

[값]: 이 속성의 데이터 값을 포함합니다. 이 값은 읽혀지고 쓰여집니다. 기본값은 정의되지 않았습니다. 예를 들어 name 속성은 위의 인스턴스 개체 person에 정의되어 있으며 해당 값은 'My name'입니다. 이 값에 대한 수정은 모두 이 위치에서 수행됩니다. configurable이 false로 설정되면 더 이상 DefineProperty를 사용하여 true로 수정할 수 없습니다(실행 시 오류가 보고됩니다: 속성을 재정의할 수 없음: propertyName)


function Person(name,age) {
 this.name = name;
 this.age = age;
 if (typeof Person._getName === "undefined"){
  Person.prototype.getName = function () {
   return this.name;
  };
  Person._getName = true;
 }
}
var person = new Person("Rose",18);
Object.defineProperty(person,"name",{configurable:false,writable:false});
person.name = "Jack";
console.log(person.name);//Rose//重新赋值无效
delete person.name;
console.log(person.name);//Rose//删除无效

Accessor property


Features:

[ configurable]: 삭제 연산자를 전달할 수 있는지 여부 속성 삭제 및 재정의 [numberable]: for-in 루프를 통해 속성을 찾을 수 있는지 여부;

[get]: 속성을 읽을 때 호출됨, 기본값: 정의되지 않음;

[set]: 속성을 작성할 때 호출됩니다. 기본값: 정의되지 않음

접근자 속성은 직접 정의할 수 없으며 다음과 같이 정의 프로퍼티() 또는 정의를 사용하여 정의해야 합니다.

function Person(name,age) {
 this.name = name;
 this.age = age;
 if (typeof Person._getName === "undefined"){
  Person.prototype.getName = function () {
   return this.name;
  };
  Person._getName = true;
 }
}
var person = new Person("Rose",18);
Object.defineProperty(person,"name",{configurable:false,writable:false});
person.name = "Jack";
console.log(person.name);//Rose//重新赋值无效
delete person.name;
console.log(person.name);//Rose//删除无效
Object.defineProperty(person,"name",{configurable:true,writable:true});//Cannot redefine property: name

모든 속성을 가져옵니다. 및 속성의 속성


Object.getOwnPropertyNames(object ) 메서드를 사용하면 모든 속성을 가져올 수 있습니다.

Object.getOwnPropertyDescriptor(object,property) 메서드를 사용하여 특정 속성의 특성을 가져옵니다.

function Person(name,age) {
 this.name = name;
 this._age = age;
 if (typeof Person._getName === "undefined"){
  Person.prototype.getName = function () {
   return this.name;
  };
  Person._getName = true;
 }
}
var person = new Person("Rose",18);
Object.defineProperty(person,"age",{
 get:function () {
  return this._age;
 },
 set:function (age) {
  this._age = age;
 }});
console.log(Object.getOwnPropertyNames(person));//["name", "_age", "age"]
console.log(Object.getOwnPropertyDescriptor(person,"age"));//{enumerable: false, configurable: false, get: function, set: function}

对于数据属性,可以取得:configurable,enumberable,writable和value;

对于访问器属性,可以取得:configurable,enumberable,get和set;

继承机制实现

对象冒充


function Father(name) {
 this.name = name ;
 this.getName = function () {
  return this.name;
 }
}
function Son(name,age) {
 this._newMethod = Father;
 this._newMethod(name);
 delete this._newMethod;

 this.age = age;
 this.getAge = function () {
  return this.age;
 }
}
var father = new Father("Tom");
var son = new Son("Jack",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//继承父类getName()方法
console.log(son.getAge());//18

多继承(利用对象冒充可以实现多继承)


function FatherA(name) {
 this.name = name ;
 this.getName = function () {
  return this.name;
 }
}
function FatherB(job) {
 this.job = job;
 this.getJob = function () {
  return this.job;
 }
}
function Son(name,job,age) {
 this._newMethod = FatherA;
 this._newMethod(name);
 delete this._newMethod;
 this._newMethod = FatherB;
 this._newMethod(job);
 delete this._newMethod;

 this.age = age;
 this.getAge = function () {
  return this.age;
 }
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//继承父类FatherA的getName()方法
console.log(son.getJob());//Programmer//继承父类FatherB的getJob()方法
console.log(son.getAge());//18

call()方法


function Father(name) {
 this.name = name ;
 this.getName = function () {
  return this.name;
 }
}
function Son(name,job,age) {
 Father.call(this,name);

 this.age = age;
 this.getAge = function () {
  return this.age;
 }
}
var father = new Father("Tom");
var son = new Son("Jack","Programmer",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//继承父类getName()方法
console.log(son.getAge());//18

多继承(利用call()方法实现多继承)


function FatherA(name) {
 this.name = name ;
 this.getName = function () {
  return this.name;
 }
}
function FatherB(job) {
 this.job = job;
 this.getJob = function () {
  return this.job;
 }
}
function Son(name,job,age) {
 FatherA.call(this,name);
 FatherB.call(this,job);

 this.age = age;
 this.getAge = function () {
  return this.age;
 }
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//继承父类FatherA的getName()方法
console.log(son.getJob());//Programmer//继承父类FatherB的getJob()方法
console.log(son.getAge());//18

apply()方法


function Father(name) {
 this.name = name ;
 this.getName = function () {
  return this.name;
 }
}
function Son(name,job,age) {
 Father.apply(this,new Array(name));

 this.age = age;
 this.getAge = function () {
  return this.age;
 }
}
var father = new Father("Tom");
var son = new Son("Jack","Programmer",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//继承父类getName()方法
console.log(son.getAge());//18

多继承(利用apply()方法实现多继承)


function FatherA(name) {
 this.name = name ;
 this.getName = function () {
  return this.name;
 }
}
function FatherB(job) {
 this.job = job;
 this.getJob = function () {
  return this.job;
 }
}
function Son(name,job,age) {
 FatherA.apply(this,new Array(name));
 FatherB.apply(this,new Array(job));

 this.age = age;
 this.getAge = function () {
  return this.age;
 }
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//继承父类FatherA的getName()方法
console.log(son.getJob());//Programmer//继承父类FatherB的getJob()方法
console.log(son.getAge());//18

原型链方法


function Father() {
}
Father.prototype.name = "Tom";
Father.prototype.getName = function () {
 return this.name;
};
function Son() {
}
Son.prototype = new Father();
Son.prototype.age = 18;
Son.prototype.getAge = function () {
 return this.age;
};
var father = new Father();
var son = new Son();
console.log(father.getName());//Tom
console.log(son.getName());//Tom//继承父类FatherA的getName()方法
console.log(son.getAge());//18

混合方式(call()+原型链)


function Father(name) {
 this.name = name;
}
Father.prototype.getName = function () {
 return this.name;
};
function Son(name,age) {
 Father.call(this,name);
 this.age = age;
}
Son.prototype = new Father();
Son.prototype.getAge = function () {
 return this.age;
};
var father = new Father("Tom");
var son = new Son("Jack",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//继承父类Father的getName()方法
console.log(son.getAge());//18

多态机制实现


function Person(name) {
 this.name = name;
 if (typeof this.getName !== "function"){
  Person.prototype.getName = function () {
   return this.name;
  }
 }
 if (typeof this.toEat !== "function"){
  Person.prototype.toEat = function (animal) {
   console.log( this.getName() + "说去吃饭:");
   animal.eat();
  }
 }
}
function Animal(name) {
 this.name = name;
 if (typeof this.getName !== "function"){
  Animal.prototype.getName = function () {
   return this.name;
  }
 }
}
function Cat(name) {
 Animal.call(this,name);
 if (typeof this.eat !== "function"){
  Cat.prototype.eat = function () {
   console.log(this.getName() + "吃鱼");
  }
 }
}
Cat.prototype = new Animal();
function Dog(name) {
 Animal.call(this,name);
 if (typeof this.eat !== "function"){
  Dog.prototype.eat = function () {
   console.log(this.getName() + "啃骨头");
  }
 }
}
Dog.prototype = new Animal();

var person = new Person("Tom");
person.toEat(new Cat("cat"));//Tom说去吃饭:cat吃鱼
person.toEat(new Dog("dog"));//Tom说去吃饭:dog啃骨头

위 내용은 JavaScript의 객체지향적 사고 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.