JavaScript는 객체 지향 프로그래밍을 지원합니다. 객체 지향 프로그래밍은 추상적인 방법을 사용하여 현실 세계에 기반한 모델을 생성하는 프로그래밍 모델입니다. 객체 지향은 JavaScript를 포함한 모듈화, 다형성 및 캡슐화 기술을 포함하여 이전에 확립된 패러다임을 사용합니다. 객체 지향 프로그래밍은 널리 사용되는 많은 프로그래밍 언어에서 지원됩니다.
이 튜토리얼의 운영 환경: Windows 10 시스템, JavaScript 버전 1.8.5, Dell G3 컴퓨터.
JavaScript의 핵심은 객체 지향을 지원하며 강력하고 유연한 OOP 언어 기능도 제공합니다. 이 기사는 객체 지향 프로그래밍에 대한 소개로 시작하여 JavaScript의 객체 모델을 탐색하고 마지막으로 JavaScript의 객체 지향 프로그래밍에 대한 몇 가지 개념을 설명합니다.
객체 지향 프로그래밍은 추상적인 방법을 사용하여 실제 세계를 기반으로 모델을 만드는 프로그래밍 모델입니다. 모듈화, 다형성, 캡슐화 등 이전에 확립된 패러다임을 사용합니다. 오늘날 널리 사용되는 많은 프로그래밍 언어(예: Java, JavaScript, C#, C++, Python, PHP, Ruby 및 Objective-C)는 객체 지향 프로그래밍(OOP)을 지원합니다.
"프로그램은 단지 기능의 모음이거나 단순한 컴퓨터 명령 목록일 뿐"이라는 전통적인 소프트웨어 설계 개념에 비해 객체 지향 프로그래밍은 일련의 객체를 사용하여 서로 협력하는 소프트웨어 설계로 볼 수 있습니다. . OOP에서 각 개체는 메시지를 수신하고, 데이터를 처리하고, 다른 개체에 메시지를 보낼 수 있습니다. 각 개체는 명확한 역할이나 책임이 있는 작은 독립 기계로 생각할 수 있습니다.
객체 지향 프로그래밍은 프로그래밍의 유연성과 유지 관리성을 향상하는 것을 목표로 하며 대규모 소프트웨어 프로젝트에서 널리 사용됩니다. 모듈성을 강조함으로써 객체 지향 코드 개발은 더 간단하고 이해하기 쉬우므로 비모듈식 프로그래밍 방법보다 복잡한 상황과 프로세스를 분석, 코딩 및 이해하는 것이 더 간단합니다.
Namespace
네임스페이스를 사용하면 개발자는 컨테이너의 모든 기능을 고유한 애플리케이션 관련 이름으로 묶을 수 있습니다.
클래스 클래스
는 객체의 특성을 정의합니다. 객체의 속성과 메소드에 대한 템플릿 정의입니다.
Object object
클래스의 인스턴스입니다.
Property Property
색상 등 물체의 특성.
방법 방법
걷기와 같은 물체의 능력.
Constructor 생성자
객체가 초기화될 때 호출되는 메서드입니다. 일반적으로 해당 이름은 해당 이름이 포함된 클래스와 일치합니다.
상속
클래스는 다른 클래스의 특성을 상속받을 수 있습니다.
Encapsulation Encapsulation
데이터를 바인딩하는 방법과 관련 방법을 함께 사용하는 것입니다.
추상화
복잡한 상속, 메소드 및 속성을 결합한 객체는 현실적인 모델을 시뮬레이션할 수 있습니다.
다형성
다형성은 "다수"를 의미하고 형태학은 "형태"를 의미합니다. 서로 다른 클래스가 동일한 메서드나 속성을 정의할 수 있습니다.
프로토타입 기반 프로그래밍은 객체 지향 프로그래밍에 구현된 스타일이 아니며, 동작 재사용(클래스 기반 언어에서는 상속이라고도 함)은 프로토타입이 포함된 기존 객체를 장식하는 과정을 통해 달성됩니다. 프로토타입 . 이 패턴은 약한 분류, 프로토타이핑 또는 인스턴스 기반 프로그래밍이라고도 합니다.
프로토타입 기반 언어의 원래(그리고 가장 일반적인) 예는 David Angell과 Randall Smith가 개발했습니다. 그러나 약하게 분류된 프로그래밍 스타일은 최근 점점 인기를 얻고 있으며 JavaScript, Cecil, NewtonScript, IO, MOO, REBOL, Kevo, Squeak(Morphic 구성 요소를 조작하기 위해 프레임워크를 사용) 및 여러 프로그래밍 언어에 채택되었습니다. 다른 프로그래밍 언어.
네임스페이스
네임스페이스는 개발자가 고유한 애플리케이션별 이름으로 모든 기능을 묶을 수 있는 컨테이너입니다. JavaScript에서 네임스페이스는 메서드, 속성 및 개체를 포함하는 또 다른 개체입니다.
참고: 다른 객체 지향 프로그래밍 언어와 달리 일반 객체와 Javascript의 네임스페이스 사이에는 언어 수준에 차이가 없다는 점을 인식하는 것이 중요합니다. JavaScript 초보자에게는 혼란스러울 수 있습니다.
JavaScript 네임스페이스를 만드는 아이디어는 간단합니다. 전역 객체가 생성되고 모든 변수, 메서드 및 함수가 해당 객체의 속성이 됩니다. 네임스페이스를 사용하면 애플리케이션의 이름 충돌 가능성도 최소화됩니다.
MYAPP
// 全局命名空间 var MYAPP = MYAPP || {};
이라는 전역 변수를 만들어 보겠습니다. 위의 코드 예에서는 먼저 MYAPP가 이미 정의되어 있는지(동일한 파일에 있는지, 다른 파일에 있는지) 확인합니다. 그렇다면 기존 MYAPP 전역 개체를 사용하고, 그렇지 않으면 MYAPP라는 빈 개체를 만들어 메서드, 함수, 변수 및 개체를 캡슐화합니다.
하위 네임스페이스를 생성할 수도 있습니다:
// 子命名空间 MYAPP.event = {};
다음은 네임스페이스를 생성하고 변수, 함수 및 메소드를 추가하는 코드입니다:
// 给普通方法和属性创建一个叫做MYAPP.commonMethod的容器 MYAPP.commonMethod = { regExForName: "", // 定义名字的正则验证 regExForPhone: "", // 定义电话的正则验证 validateName: function(name){ // 对名字name做些操作,你可以通过使用“this.regExForname” // 访问regExForName变量 }, validatePhoneNo: function(phoneNo){ // 对电话号码做操作 } } // 对象和方法一起申明 MYAPP.event = { addListener: function(el, type, fn) { // 代码 }, removeListener: function(el, type, fn) { // 代码 }, getEvent: function(e) { // 代码 } // 还可以添加其他的属性和方法 } //使用addListener方法的写法: MYAPP.event.addListener("yourel", "type", callback);
표준 내장 객체
JavaScript有包括在其核心的几个对象,例如,Math,Object,Array和String对象。下面的例子演示了如何使用Math对象的random()方法来获得一个随机数。
console.log(Math.random());
注意:这里和接下来的例子都假设名为 console.log 的方法全局有定义。console.log 实际上不是 JavaScript 自带的。
查看 JavaScript 参考:全局对象 了解 JavaScript 内置对象的列表。
JavaScript 中的每个对象都是 Object 对象的实例且继承它所有的属性和方法。
自定义对象
类
JavaScript 是一种基于原型的语言,它没类的声明语句,比如 C+ + 或 Java 中用的。这有时会对习惯使用有类申明语句语言的程序员产生困扰。相反,JavaScript可用方法作类。定义一个类跟定义一个函数一样简单。在下面的例子中,我们定义了一个新类Person。
function Person() { } // 或 var Person = function(){ }
对象(类的实例)
我们使用 new obj 创建对象 obj 的新实例, 将结果(obj 类型)赋值给一个变量方便稍后调用。
在下面的示例中,我们定义了一个名为Person的类,然后我们创建了两个Person的实例(person1 and person2)。
function Person() { } var person1 = new Person(); var person2 = new Person();
注意:有一种新增的创建未初始化实例的实例化方法,请参考 Object.create 。
构造器
在实例化时构造器被调用 (也就是对象实例被创建时)。构造器是对象中的一个方法。 在JavaScript中函数就可以作为构造器使用,因此不需要特别地定义一个构造器方法,每个声明的函数都可以在实例化后被调用执行。
构造器常用于给对象的属性赋值或者为调用函数做准备。 在本文的后面描述了类中方法既可以在定义时添加,也可以在使用前添加。
在下面的示例中, Person类实例化时构造器调用一个 alert函数。
function Person() { alert('Person instantiated'); } var person1 = new Person(); var person2 = new Person();
属性 (对象属性)
属性就是 类中包含的变量;每一个对象实例有若干个属性. 为了正确的继承,属性应该被定义在类的原型属性 (函数)中。
可以使用 关键字 this调用类中的属性, this是对当前对象的引用。 从外部存取(读/写)其属性的语法是: InstanceName.Property; 这与C++,Java或者许多其他语言中的语法是一样的 (在类中语法 this.Property 常用于set和get属性值)
在下面的示例中,我们为定义Person类定义了一个属性 firstName 并在实例化时赋初值。
function Person(firstName) { this.firstName = firstName; alert('Person instantiated'); } var person1 = new Person('Alice'); var person2 = new Person('Bob'); // Show the firstName properties of the objects alert('person1 is ' + person1.firstName); // alerts "person1 is Alice" alert('person2 is ' + person2.firstName); // alerts "person2 is Bob"
方法(对象属性)
方法与属性很相似, 不同的是:一个是函数,另一个可以被定义为函数。 调用方法很像存取一个属性, 不同的是add () 在方法名后面很可能带着参数。为定义一个方法, 需要将一个函数赋值给类的 prototype 属性; 这个赋值给函数的名称就是用来给对象在外部调用它使用的。
在下面的示例中,我们给Person类定义了方法 sayHello(),并调用了它。
function Person(firstName) { this.firstName = firstName; } Person.prototype.sayHello = function() { alert("Hello, I'm " + this.firstName); }; var person1 = new Person("Alice"); var person2 = new Person("Bob"); // call the Person sayHello method. person1.sayHello(); // alerts "Hello, I'm Alice" person2.sayHello(); // alerts "Hello, I'm Bob"
在JavaScript中方法通常是一个绑定到对象中的普通函数, 这意味着方法可以在其所在context之外被调用。 思考下面示例中的代码:
function Person(firstName) { this.firstName = firstName; } Person.prototype.sayHello = function() { alert("Hello, I'm " + this.firstName); }; var person1 = new Person("Alice"); var person2 = new Person("Bob"); var helloFunction = person1.sayHello; person1.sayHello(); // alerts "Hello, I'm Alice" person2.sayHello(); // alerts "Hello, I'm Bob" helloFunction(); // alerts "Hello, I'm undefined" (or fails with a TypeError in strict mode) console.log(helloFunction === person1.sayHello); // logs true console.log(helloFunction === Person.prototype.sayHello); // logs true helloFunction.call(person1); // logs "Hello, I'm Alice"
如上例所示, 所有指向sayHello函数的引用 ,包括 person1, Person.prototype, 和 helloFunction 等, 均引用了相同的函数.
在调用函数的过程中,this的值取决于我们怎么样调用函数. 在通常情况下,我们通过一个表达式person1.sayHello()来调用函数:即从一个对象的属性中得到所调用的函数。此时this被设置为我们取得函数的对象(即person1)。这就是为什么person1.sayHello() 使用了姓名“Alice”而person2.sayHello()使用了姓名“bob”的原因。
然而我们使用不同的调用方法时, this的值也就不同了。当从变量 helloFunction()中调用的时候, this就被设置成了全局对象 (在浏览器中即window)。由于该对象 (非常可能地) 没有firstName 属性, 我们得到的结果便是"Hello, I'm undefined". (这是松散模式下的结果, 在 严格模式中,结果将不同(此时会产生一个error)。 但是为了避免混淆,我们在这里不涉及细节) 。另外,我们可以像上例末尾那样,使用Function#call (或者Function#apply)显式的设置this的值。
更多有关信息请参考 Function#call and Function#apply
继承
创建一个或多个类的专门版本类方式称为继承(Javascript只支持单继承)。 创建的专门版本的类通常叫做子类,另外的类通常叫做父类。 在Javascript中,继承通过赋予子类一个父类的实例并专门化子类来实现。在现代浏览器中你可以使用 Object.create 实现继承。
JavaScript 并不检测子类的 prototype.constructor (见 Object.prototype), 所以我们必须手动申明它。
在下面的例子中, 我们定义了 Student类作为 Person类的子类。 之后我们重定义了sayHello() 方法并添加了 sayGoodBye() 方法。
// 定义Person构造器 function Person(firstName) { this.firstName = firstName; } // 在Person.prototype中加入方法 Person.prototype.walk = function(){ alert("I am walking!"); }; Person.prototype.sayHello = function(){ alert("Hello, I'm " + this.firstName); }; // 定义Student构造器 function Student(firstName, subject) { // 调用父类构造器, 确保(使用Function#call)"this" 在调用过程中设置正确 Person.call(this, firstName); // 初始化Student类特有属性 this.subject = subject; }; // 建立一个由Person.prototype继承而来的Student.prototype对象. // 注意: 常见的错误是使用 "new Person()"来建立Student.prototype. // 这样做的错误之处有很多, 最重要的一点是我们在实例化时 // 不能赋予Person类任何的FirstName参数 // 调用Person的正确位置如下,我们从Student中来调用它 Student.prototype = Object.create(Person.prototype); // See note below // 设置"constructor" 属性指向Student Student.prototype.constructor = Student; // 更换"sayHello" 方法 Student.prototype.sayHello = function(){ console.log("Hello, I'm " + this.firstName + ". I'm studying " + this.subject + "."); }; // 加入"sayGoodBye" 方法 Student.prototype.sayGoodBye = function(){ console.log("Goodbye!"); }; // 测试实例: var student1 = new Student("Janet", "Applied Physics"); student1.sayHello(); // "Hello, I'm Janet. I'm studying Applied Physics." student1.walk(); // "I am walking!" student1.sayGoodBye(); // "Goodbye!" // Check that instanceof works correctly console.log(student1 instanceof Person); // true console.log(student1 instanceof Student); // true
对于 “ Student.prototype = Object.create(Person.prototype); ” 这一行,在不支持 Object.create 方法的老 JavaScript 引擎中,可以使用一个 "polyfill"(又名"shim",查看文章链接),或者使用一个 function 来获得相同的返回值,就像下面:
function createObject(proto) { function ctor() { } ctor.prototype = proto; return new ctor(); } // Usage: Student.prototype = createObject(Person.prototype);
更多相关信息请参考 Object.create,连接中还有一个老JavaScript引擎的兼容方案(shim)。
封装
在上一个例子中,Student类虽然不需要知道Person类的walk()方法是如何实现的,但是仍然可以使用这个方法;Student类不需要明确地定义这个方法,除非我们想改变它。 这就叫做封装,对于所有继承自父类的方法,只需要在子类中定义那些你想改变的即可。
抽象
抽象是允许模拟工作问题中通用部分的一种机制。这可以通过继承(具体化)或组合来实现。
JavaScript通过继承实现具体化,通过让类的实例是其他对象的属性值来实现组合。
JavaScript Function 类继承自Object类(这是典型的具体化) 。Function.prototype的属性是一个Object实例(这是典型的组合)。
var foo = function(){}; console.log( 'foo is a Function: ' + (foo instanceof Function) ); // logs "foo is a Function: true" console.log( 'foo.prototype is an Object: ' + (foo.prototype instanceof Object) ); // logs "foo.prototype is an Object: true"
多态
就像所有定义在原型属性内部的方法和属性一样,不同的类可以定义具有相同名称的方法;方法是作用于所在的类中。并且这仅在两个类不是父子关系时成立(继承链中,一个类不是继承自其他类)。
相关推荐:javascript学习教程
위 내용은 자바스크립트는 객체지향을 지원하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!