이 기사의 예에서는 JavaScript에서 클래스를 정의하는 방법을 설명합니다. 참고하실 수 있도록 모든 사람과 공유하세요. 자세한 내용은 다음과 같습니다.
Javascript 자체는 객체 지향을 지원하지 않고, 액세스 제어 문자가 없으며, 클래스를 정의하는 키워드 class가 없으며, 상속을 위해 확장이나 콜론을 지원하지 않으며, virtual을 사용하여 virtual을 지원하지 않습니다. 그러나 Javascript는 유연한 언어이므로 class라는 키워드가 없는 Javascript가 어떻게 클래스 정의를 구현하고 객체를 생성하는지 살펴보겠습니다.
1. 클래스를 정의하고 해당 클래스의 인스턴스 객체를 생성합니다
Javascript에서는 다음과 같이 함수를 사용하여 클래스를 정의합니다.
function Shape() { var x = 1 ; var y = 2 ; }
의심스럽다고 말할 수 있을까요? 이것은 정의 기능이 아닌가? 예, 이것은 정의 함수입니다. Shape 함수를 정의하고 x와 y를 초기화합니다. 그러나 다른 각도에서 보면 이는 x와 y라는 두 개의 속성을 갖는 Shape 클래스를 정의하는 것이며 초기값은 각각 1과 2이다. 클래스는 클래스가 아니라 함수입니다.
그런 다음 다음과 같이 Shape 클래스의 aShape 객체를 생성할 수 있습니다.
2. 공개 및 비공개 속성을 정의합니다.
aShape 개체를 생성했지만 해당 속성에 액세스하려고 하면 다음과 같은 오류가 발생합니다.
이는 var로 정의된 속성이 비공개임을 나타냅니다. 공개 속성을 정의하려면 이 키워드를 사용해야 합니다
function Shape() { this .x = 1 ; this .y = 2 ; }
이런 방식으로 Shape의 속성에 액세스할 수 있습니다.
좋아, 위의 코드를 기반으로 요약할 수 있습니다. var를 사용하여 클래스의 비공개 속성을 정의하고 이를 사용하여 클래스의 공개 속성을 정의합니다.
3. 공개 메소드와 비공개 메소드를 정의하세요
Javascript에서 함수는 Function 클래스의 인스턴스입니다. 따라서 함수도 객체이므로 함수를 생성할 수 있습니다. 클래스에 함수를 할당하면 이 속성 변수는 실행 가능한 함수이므로 메서드라고 부를 수 있습니다. 코드는 다음과 같습니다.
function Shape() { var x = 0 ; var y = 1 ; this .draw = function () { // print; }; }
위 코드에서 draw를 정의하고 여기에 함수를 할당했습니다. 다음으로 OOP에서 공개 메서드라고 하는 aShape를 통해 이 함수를 호출할 수 있습니다.
var로 정의하면 이 그리기는 비공개가 됩니다. 이를 OOP에서는 비공개 메서드라고 합니다.
function Shape() { var x = 0 ; var y = 1 ; var draw = function () { // print; }; }
이렇게 하면 aShape.draw를 사용하여 이 함수를 호출할 수 없습니다.
3. 생성자
Javascript는 OOP를 지원하지 않으며 물론 생성자가 없습니다. 그러나 생성자를 직접 시뮬레이션하여 객체가 생성될 때 자동으로 호출되도록 할 수 있습니다.
function Shape() { var init = function () { // 构造函数代码 }; init(); }
Shape의 마지막에는 init 함수를 인위적으로 호출했습니다. 그런 다음 Shape 객체가 생성되면 항상 init가 자동으로 호출되고 생성자를 시뮬레이션할 수 있습니다.
4. 매개변수가 있는 생성자
생성자가 매개변수를 사용하도록 하려면 어떻게 해야 하나요? 사실 아주 간단합니다.
처럼 함수의 매개변수 목록에 전달할 매개변수를 작성하면 됩니다.function Shape(ax,ay) { var x = 0 ; var y = 0 ; var init = function () { // 构造函数 x = ax; y = ay; }; init(); }
이런 방법으로 다음과 같은 개체를 만들 수 있습니다.
5. 정적 속성 및 정적 메서드
Javascript에서 정적 속성과 메서드를 어떻게 정의하나요? 아래와 같이
function Shape(ax,ay) { var x = 0 ; var y = 0 ; var init = function () { // 构造函数 x = ax; y = ay; }; init(); } Shape.count = 0 ; // 定义一个静态属性count,这个属性是属于类的,不是属于对象的。 Shape.staticMethod = function (){}; // 定义一个静态的方法
정적 속성과 메서드를 사용하면 다음과 같이 클래스 이름을 사용하여 액세스할 수 있습니다
alert ( aShape.count ); aShape.staticMethod();
注意:静态属性和方法都是公有的,目前为止,我不知道如何让静态属性和方法变成私有的~
六、在方法中访问本类的公有属性和私有属性
在类的方法中访问自己的属性,Javascript对于公有属性和私有属性的访问方法有所不同,请大家看下面的代码
function Shape(ax,ay) { var x = 0 ; var y = 0 ; this .gx = 0 ; this .gy = 0 ; var init = function () { x = ax; // 访问私有属性,直接写变量名即可 y = ay; this .gx = ax; // 访问公有属性,需要在变量名前加上this. this .gy = ay; }; init(); }
七、this的注意事项
根据笔者的经验,类中的this并不是一直指向我们的这个对象本身的,主要原因还是因为Javascript并不是OOP语言,而且,函数和类均用function定义,当然会引起一些小问题。
this指针指错的场合一般在事件处理上面,我们想让某个对象的成员函数来响应某个事件,当事件被触发以后,系统会调用我们这个成员函数,但是,传入的this指针已经不是我们本身的对象了,当然,这时再在成员函数中调用this当然会出错了。
解决方法是我们在定义类的一开始就将this保存到一个私有的属性中,以后,我们可以用这个属性代替this。我用这个方法使用this指针相当安全,而且很是省心~
我们修改一下代码,解决this问题。对照第六部分的代码看,你一定就明白了
function Shape(ax,ay) { var _this = this ; // 把this保存下来,以后用_this代替this,这样就不会被this弄晕了 var x = 0 ; var y = 0 ; _this.gx = 0 ; _this.gy = 0 ; var init = function () { x = ax; // 访问私有属性,直接写变量名即可 y = ay; _this.gx = ax; // 访问公有属性,需要在变量名前加上this. _this.gy = ay; }; init(); }
以上我们聊了如何在Javascript中定义类,创建类的对象,创建公有和私有的属性和方法,创建静态属性和方法,模拟构造函数,并且讨论了容易出错的this。
关于Javascript中的OOP实现就聊到这里,以上是最实用的内容,一般用Javascript定义类,创建对象用以上的代码已经足够了。当然,你还可以用mootools或prototype来定义类,创建对象。我用过mootools框架,感觉很不错,它对Javascript的类模拟就更完善了,还支持类的继承,有兴趣的读者可以去尝试一下。当然,如果使用了框架,那么在你的网页中就需要包含相关的js头文件,因此我还是希望读者能够在没有框架的情况下创建类,这样,代码效率较高,而且你也可以看到,要创建一个简单的类并不麻烦~
补充:
JavaScript类定义的四种方式:
// 1、工厂方式 function createCar(name,color,price){ var tempcar=new Object; tempcar.name=name; tempcar.color=color; tempcar.price=price; tempcar.getName=function(){ document.write(this.name+"-----"+this.color+"<br>"); }; return tempcar; } var car1=new createCar("工厂桑塔纳","red","121313"); car1.getName(); /* 定义了一个能创建并返回特定类型对象的工厂函数, 看起来还是不错的, 但有个小问题 , 每次调用时都要创建新函数 showColor,我们可以把它移到函数外面, function getName(){ document.write(this.name+"-----"+this.color+"<br>"); } 在工厂函数中直接指向它 tempCar.getName = getName; 这样避免了重复创建函数的问题,但看起来不像对象的方法了。 */ // 2、构造函数方式 function Car(name,color,price){ this.name=name; this.color=color; this.price=price; this.getColor=function(){ document.write(this.name+"-----"+this.color+"<br>"); }; } var car2=new Car("构造桑塔纳","red","121313"); car2.getColor(); /* 可以看到与第一中方式的差别,在构造函数内部无创建对象,而是使用 this 关键字。 使用 new 调用构造函数时,先创建了一个对象,然后用 this 来访问。 这种用法于其他面向对象语言很相似了, 但这种方式和上一种有同一个问题, 就是重复创建函数。 */ // 3、原型方式 function proCar(){ } proCar.prototype.name="原型"; proCar.prototype.color="blue"; proCar.prototype.price="10000"; proCar.prototype.getName=function(){ document.write(this.name+"-----"+this.color+"<br>"); }; var car3=new proCar(); car3.getName(); /* 首先定义了构造函数 Car,但无任何代码,然后通过 prototype 添加属性。优点: a. 所有实例存放的都是指向 showColor 的指针,解决了重复创建函数的问题 b. 可以用 instanceof 检查对象类型 alert(car3 instanceof proCar);//true 缺点,添加下面的代码: proCar.prototype.drivers = newArray("mike", "sue"); car3.drivers.push("matt"); alert(car3.drivers);//outputs "mike,sue,matt" alert(car3.drivers);//outputs "mike,sue,matt" drivers 是指向 Array 对象的指针,proCar 的两个实例都指向同一个数组。 */ // 4、动态原型方式 function autoProCar(name,color,price){ this.name=name; this.color=color; this.price=price; this.drives=new Array("mike","sue"); if(typeof autoProCar.initialized== "undefined"){ autoProCar.prototype.getName =function(){ document.write(this.name+"-----"+this.color+"<br>"); }; autoProCar.initialized=true; } } var car4=new autoProCar("动态原型","yellow","1234565"); car4.getName(); car4.drives.push("newOne"); document.write(car4.drives); /* 这种方式是我最喜欢的, 所有的类定义都在一个函数中完成, 看起来非常像其他语言的 类定义,不会重复创建函数,还可以用 instanceof */
希望本文所述对大家JavaScript程序设计有所帮助。