首页 > 语言 > JavaScript > 正文

每天一篇javascript学习小结(面向对象编程)

2024-05-06 16:25:09
字体:大 中 小
来源:转载
供稿:网友

这篇文章主要介绍了javascript中的面向对象编程知识点,对面向对象编程进行概述,以及各种方法进行整理,感兴趣的小伙伴们可以参考一下

1、面向对象的工厂方法

 

 
  1. function createPerson(name, age, job){ 
  2. var o = new Object(); 
  3. o.name = name; 
  4. o.age = age; 
  5. o.job = job; 
  6. o.sayName = function(){ 
  7. alert(this.name); 
  8. };  
  9. return o; 
  10. } 
  11.  
  12. var person1 = createPerson("Nicholas", 29, "Software Engineer"); 
  13. var person2 = createPerson("Greg", 27, "Doctor"); 
  14.  
  15. person1.sayName(); //"Nicholas" 
  16. person2.sayName(); //"Greg" 

工厂模型的方法的缺点是会产生大量重复代码!

2、构造函数模式创建对象

 

 
  1. function Person(name, age, job){ 
  2. this.name = name; 
  3. this.age = age; 
  4. this.job = job; 
  5. this.sayName = function(){ 
  6. alert(this.name); 
  7. };  
  8. } 
  9.  
  10. var person1 = new Person("Nicholas", 29, "Software Engineer"); 
  11. var person2 = new Person("Greg", 27, "Doctor"); 
  12.  
  13. person1.sayName(); //"Nicholas" 
  14. person2.sayName(); //"Greg" 
  15.  
  16. alert(person1 instanceof Object); //true 
  17. alert(person1 instanceof Person); //true 
  18. alert(person2 instanceof Object); //true 
  19. alert(person2 instanceof Person); //true 
  20.  
  21. alert(person1.constructor == Person); //true 
  22. alert(person2.constructor == Person); //true 
  23.  
  24. alert(person1.sayName == person2.sayName); //false 

使用new关键字创建对象会经历以下四个过程

1、创建一个新对象

2、将构造函数的作用域赋给一个新对象(因此this就指向了这个新对象)

3、执行构造函数的方法(为这个新对象赋值)

4、返回新对象

3、将构造函数当函数用

 

 
  1. function Person(name, age, job){ 
  2. this.name = name; 
  3. this.age = age; 
  4. this.job = job; 
  5. this.sayName = function(){ 
  6. alert(this.name); 
  7. }; 
  8. } 
  9.  
  10. var person = new Person("Nicholas", 29, "Software Engineer"); 
  11. person.sayName(); //"Nicholas" 
  12.  
  13. Person("Greg", 27, "Doctor"); //adds to window 
  14. window.sayName(); //"Greg" 
  15.  
  16. var o = new Object(); 
  17. Person.call(o, "Kristen", 25, "Nurse"); 
  18. o.sayName(); //"Kristen" 

构造函数当做函数使用就和普通的函数没有任何不同,它属于window对象下面添加的方法而已。由于构造函数创建的对象实际上是创建一个新对象,因此在本质上两者还是不一样的,还是分离的,他们的方法还是不一样的!

4、将共有的方法方法全局解决不一致的问题

 

 
  1. function Person(name, age, job){ 
  2. this.name = name; 
  3. this.age = age; 
  4. this.job = job; 
  5. this.sayName = sayName; 
  6. } 
  7.  
  8. function sayName(){ 
  9. alert(this.name); 
  10. } 
  11.  
  12. var person1 = new Person("Nicholas", 29, "Software Engineer"); 
  13. var person2 = new Person("Greg", 27, "Doctor"); 
  14.  
  15. person1.sayName(); //"Nicholas" 
  16. person2.sayName(); //"Greg" 
  17.  
  18. alert(person1 instanceof Object); //true 
  19. alert(person1 instanceof Person); //true 
  20. alert(person2 instanceof Object); //true 
  21. alert(person2 instanceof Person); //true 
  22.  
  23. alert(person1.constructor == Person); //true 
  24. alert(person2.constructor == Person); //true 
  25.  
  26. alert(person1.sayName == person2.sayName); //true 

虽然上面的方法解决了一致的问题,但是定义的全局的方法本身属于window,那么局部和全局就没有分开!所以这个方法使用的并不多见!也不建议使用。

5、原型模式

我们创建的任何的一个函数都有一个原型对象,这个属性是一个指针,它指向一个对象,而这个对象的作用是可以有特定的类型的所有的实例共享的方法!

 

 
  1. function Person(){ 
  2. } 
  3.  
  4. Person.prototype.name = "Nicholas"; 
  5. Person.prototype.age = 29; 
  6. Person.prototype.job = "Software Engineer"; 
  7. Person.prototype.sayName = function(){ 
  8. alert(this.name); 
  9. }; 
  10.  
  11. var person1 = new Person(); 
  12. person1.sayName(); //"Nicholas" 
  13.  
  14. var person2 = new Person(); 
  15. person2.sayName(); //"Nicholas" 
  16.  
  17. alert(person1.sayName == person2.sayName); //true 
  18.  
  19. alert(Person.prototype.isPrototypeOf(person1)); //true 
  20. alert(Person.prototype.isPrototypeOf(person2)); //true 
  21.  
  22. //only works if Object.getPrototypeOf() is available 
  23. if (Object.getPrototypeOf){ 
  24. alert(Object.getPrototypeOf(person1) == Person.prototype); //true 
  25. alert(Object.getPrototypeOf(person1).name); //"Nicholas" 
  26. } 

理解原型

无论什么时候只要是创建了一个函数,就会创建一个原型属性,这个属性指向函数的原型对象。在默认的情况下,原型对象都会包含一个constructor(构造函数属性),这个属性包含一个指向prototype属性所在函数的指针!

属性读取的顺序

每当代码读取某个对象的属性时候,都会执行一次搜索,目标是具有给定名字的属性,搜索从对象的实例本身开始查找,如有则返回,没有则继续搜索该对象的原型链,直至搜索到原型链的最外层!

 

 
  1. function Person(){ 
  2. } 
  3.  
  4. Person.prototype.name = "Nicholas"; 
  5. Person.prototype.age = 29; 
  6. Person.prototype.job = "Software Engineer"; 
  7. Person.prototype.sayName = function(){ 
  8. alert(this.name); 
  9. }; 
  10.  
  11. var person1 = new Person(); 
  12. var person2 = new Person(); 
  13.  
  14. person1.name = "Greg"; 
  15. alert(person1.name); //"Greg" 来自实例 
  16. alert(person2.name); //"Nicholas" 来自原型 

如果删除了这个元素的实例属性

 

 
  1. function Person(){ 
  2. } 
  3.  
  4. Person.prototype.name = "Nicholas"; 
  5. Person.prototype.age = 29; 
  6. Person.prototype.job = "Software Engineer"; 
  7. Person.prototype.sayName = function(){ 
  8. alert(this.name); 
  9. }; 
  10.  
  11. var person1 = new Person(); 
  12. var person2 = new Person(); 
  13.  
  14. person1.name = "Greg"; 
  15. alert(person1.name); //"Greg" ?from instance 
  16. alert(person2.name); //"Nicholas" ?from prototype 
  17.  
  18. delete person1.name; 
  19. alert(person1.name); //"Nicholas" - from the prototype 

6、hasOwnProperty方法

这个方法可以检测一个属性是否存在于实例中,还是存在于原型中!hasOwnProperty是从Object继承来的,只要给定属性存在于对象实例中,才会返回true.

 

 
  1. function Person(){ 
  2. } 
  3.  
  4. Person.prototype.name = "Nicholas"; 
  5. Person.prototype.age = 29; 
  6. Person.prototype.job = "Software Engineer"; 
  7. Person.prototype.sayName = function(){ 
  8. alert(this.name); 
  9. }; 
  10.  
  11. var person1 = new Person(); 
  12. var person2 = new Person(); 
  13.  
  14. alert(person1.hasOwnProperty("name")); //false 
  15. alert("name" in person1); //true 
  16.  
  17. person1.name = "Greg"; 
  18. alert(person1.name); //"Greg" ?from instance 
  19. alert(person1.hasOwnProperty("name")); //true 
  20. alert("name" in person1); //true 
  21.  
  22. alert(person2.name); //"Nicholas" ?from prototype 
  23. alert(person2.hasOwnProperty("name")); //false 
  24. alert("name" in person2); //true 
  25.  
  26. delete person1.name; 
  27. alert(person1.name); //"Nicholas" - from the prototype 
  28. alert(person1.hasOwnProperty("name")); //false 
  29. alert("name" in person1); //true 

7、Object.keys() 可枚举属性方法

这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组

 

 
  1. function Person(){ 
  2. } 
  3.  
  4. Person.prototype.name = "Nicholas"; 
  5. Person.prototype.age = 29; 
  6. Person.prototype.job = "Software Engineer"; 
  7. Person.prototype.sayName = function(){ 
  8. alert(this.name); 
  9. }; 
  10.  
  11. var keys = Object.keys(Person.prototype); 
  12. alert(keys); //"name,age,job,sayName" 
  13. 如果想得到所有实例的属性,无论它是否可以枚举都可以使用这个方法来获取 
  14. function Person(){ 
  15. } 
  16.  
  17. Person.prototype.name = "Nicholas"; 
  18. Person.prototype.age = 29; 
  19. Person.prototype.job = "Software Engineer"; 
  20. Person.prototype.sayName = function(){ 
  21. alert(this.name); 
  22. }; 
  23.  
  24. var keys = Object.getOwnPropertyNames(Person.prototype); 
  25. alert(keys); //"constructor,name,age,job,sayName" 

此方法高版本浏览器才支持

8、简单的原型写法

 

 
  1. function Person(){ 
  2. } 
  3.  
  4. Person.prototype = { 
  5. name : "Nicholas", 
  6. age : 29, 
  7. job: "Software Engineer", 
  8. sayName : function () { 
  9. alert(this.name); 
  10. } 
  11. }; 
  12.  
  13. var friend = new Person(); 
  14.  
  15. alert(friend instanceof Object); //true 
  16. alert(friend instanceof Person); //true 
  17. alert(friend.constructor == Person); //false 
  18. alert(friend.constructor == Object); //true 

重写了原型就等于将默认的原型方法覆盖,那么同样的构造方法也会被重写,重写的构造方法指向了Object对象!而不是原来的对象Person

如果还是想指向之前的构造方法,可以显示的指定

 

 
  1. function Person(){ 
  2. } 
  3.  
  4. Person.prototype = { 
  5. constructor : Person, 
  6. name : "Nicholas", 
  7. age : 29, 
  8. job: "Software Engineer", 
  9. sayName : function () { 
  10. alert(this.name); 
  11. } 
  12. }; 
  13.  
  14. var friend = new Person(); 
  15.  
  16. alert(friend instanceof Object); //true 
  17. alert(friend instanceof Person); //true 
  18. alert(friend.constructor == Person); //true 
  19. alert(friend.constructor == Object); //false 

9、原型方法的动态添加

 

 
  1. function Person(){ 
  2. } 
  3.  
  4. Person.prototype = { 
  5. constructor: Person, 
  6. name : "Nicholas", 
  7. age : 29, 
  8. job : "Software Engineer", 
  9. sayName : function () { 
  10. alert(this.name); 
  11. } 
  12. }; 
  13.  
  14. var friend = new Person(); 
  15.  
  16. Person.prototype.sayHi = function(){ 
  17. alert("hi"); 
  18. }; 
  19.  
  20. friend.sayHi(); //"hi" ?works! 

10、原生对象的原型方法

 

 
  1. alert(typeof Array.prototype.sort); //"function" 
  2. alert(typeof String.prototype.substring); //"function" 
  3.  
  4. String.prototype.startsWith = function (text) {//修改原生对象的原型方法 
  5. return this.indexOf(text) == 0; 
  6. }; 
  7.  
  8. var msg = "Hello world!"; 
  9. alert(msg.startsWith("Hello")); //true 

11、组合使用构造函数和原型模式创建对象

 

 
  1. //构造函数模式 
  2. function Person(name, age, job){ 
  3. this.name = name; 
  4. this.age = age; 
  5. this.job = job; 
  6. this.friends = ["Shelby", "Court"]; 
  7. } 
  8. //原型模式 
  9. Person.prototype = { 
  10. constructor: Person, 
  11. sayName : function () { 
  12. alert(this.name); 
  13. } 
  14. }; 
  15.  
  16. var person1 = new Person("Nicholas", 29, "Software Engineer"); 
  17. var person2 = new Person("Greg", 27, "Doctor"); 
  18.  
  19. person1.friends.push("Van"); 
  20.  
  21. alert(person1.friends); //"Shelby,Court,Van" 
  22. alert(person2.friends); //"Shelby,Court" 
  23. alert(person1.friends === person2.friends); //false 
  24. alert(person1.sayName === person2.sayName); //true 

12、动态原型模式

 

 
  1. function Person(name, age, job){ 
  2.  
  3. //properties 
  4. this.name = name; 
  5. this.age = age; 
  6. this.job = job; 
  7.  
  8. //methods 
  9. if (typeof this.sayName != "function"){ 
  10.  
  11. Person.prototype.sayName = function(){ 
  12. alert(this.name); 
  13. }; 
  14.  
  15. } 
  16. } 
  17.  
  18. var friend = new Person("Nicholas", 29, "Software Engineer"); 
  19. friend.sayName(); 

13、寄生构造函数模式

 

 
  1. function Person(name, age, job){ 
  2. var o = new Object();//依赖全局对象初始化一个对象,然后再返回这个对象 
  3. o.name = name; 
  4. o.age = age; 
  5. o.job = job; 
  6. o.sayName = function(){ 
  7. alert(this.name); 
  8. };  
  9. return o; 
  10. } 
  11.  
  12. var friend = new Person("Nicholas", 29, "Software Engineer"); 
  13. friend.sayName(); //"Nicholas" 
  14.  
  15. function SpecialArray(){  
  16.  
  17. //create the array 
  18. var values = new Array(); 
  19.  
  20. //add the values 
  21. values.push.apply(values, arguments); 
  22.  
  23. //assign the method 
  24. values.toPipedString = function(){ 
  25. return this.join("|"); 
  26. }; 
  27.  
  28. //return it 
  29. return values;  
  30. } 
  31.  
  32. var colors = new SpecialArray("red", "blue", "green"); 
  33. alert(colors.toPipedString()); //"red|blue|green" 
  34.  
  35. alert(colors instanceof SpecialArray); 

上诉方法有一点说明下,由于它是依赖外层对象来创建一个新对象,因此不能依赖 instanceof方法来确定属性和方法的来源!它实际上和构造函数的没有关系!

14、稳妥构造函数模式

 

 
  1. function Person(name, age, job){ 
  2. var o = new Object(); 
  3. o.sayName = function(){ 
  4. alert(name); 
  5. };  
  6. return o; 
  7. } 
  8.  
  9. var friend = Person("Nicholas", 29, "Software Engineer"); 
  10. friend.sayName(); //"Nicholas" 

此方法不依赖任何new this 关键符!如果要访问对象的方法和属性,只能通过对象已经定义好的方法来获取!

15、继承

javascript实现继承是通过原型链来实现的

 

 
  1. function SuperType(){ 
  2. this.property = true;//定义一个属性 
  3. } 
  4.  
  5. SuperType.prototype.getSuperValue = function(){//定义的原型方法 
  6. return this.property; 
  7. }; 
  8.  
  9. function SubType(){ 
  10. this.subproperty = false; 
  11. } 
  12.  
  13. //inherit from SuperType 
  14. SubType.prototype = new SuperType(); 
  15.  
  16. SubType.prototype.getSubValue = function (){ 
  17. return this.subproperty; 
  18. }; 
  19.  
  20. var instance = new SubType(); 
  21. alert(instance.getSuperValue()); //true 
  22.  
  23. alert(instance instanceof Object); //true 
  24. alert(instance instanceof SuperType); //true 
  25. alert(instance instanceof SubType); //true 
  26.  
  27. alert(Object.prototype.isPrototypeOf(instance)); //true 
  28. alert(SuperType.prototype.isPrototypeOf(instance)); //true 
  29. alert(SubType.prototype.isPrototypeOf(instance)); //true 
  30. SubType继承SuperType的方法和属性,因此当instance可以直接调用SuperType的方法! 
  31. function SuperType(){ 
  32. this.property = true; 
  33. } 
  34.  
  35. SuperType.prototype.getSuperValue = function(){ 
  36. return this.property; 
  37. }; 
  38.  
  39. function SubType(){ 
  40. this.subproperty = false; 
  41. } 
  42.  
  43. //inherit from SuperType 
  44. SubType.prototype = new SuperType(); 
  45.  
  46. //new method 
  47. SubType.prototype.getSubValue = function (){ 
  48. return this.subproperty; 
  49. }; 
  50.  
  51. //override existing method 
  52. SubType.prototype.getSuperValue = function (){ 
  53. return false; 
  54. }; 
  55.  
  56. var instance = new SubType(); 
  57. alert(instance.getSuperValue()); //false 

上面的例子说明,重写的原型会覆盖之前继承的原型,最后返回的往往不是预期的效果

 

 
  1. function SuperType(){ 
  2. this.property = true; 
  3. } 
  4.  
  5. SuperType.prototype.getSuperValue = function(){ 
  6. return this.property; 
  7. }; 
  8.  
  9. function SubType(){ 
  10. this.subproperty = false; 
  11. } 
  12.  
  13. //inherit from SuperType 
  14. SubType.prototype = new SuperType(); 
  15.  
  16. //使用字面量添加的方法导致上面的方法失效了 
  17. SubType.prototype = { 
  18. getSubValue : function (){ 
  19. return this.subproperty; 
  20. }, 
  21.  
  22. someOtherMethod : function (){ 
  23. return false; 
  24. } 
  25. };  
  26.  
  27. var instance = new SubType(); 
  28. console.log(instance); 
  29. alert(instance.getSuperValue()); //error! 

下面的例子也说明重写原型带来的风险

 

 
  1. function SuperType(){ 
  2. this.colors = ["red", "blue", "green"]; 
  3. } 
  4.  
  5. function SubType(){  
  6. } 
  7.  
  8. //inherit from SuperType 
  9. SubType.prototype = new SuperType(); 
  10.  
  11. var instance1 = new SubType(); 
  12. instance1.colors.push("black"); 
  13. alert(instance1.colors); //"red,blue,green,black" 
  14.  
  15. var instance2 = new SubType(); 
  16. alert(instance2.colors); //"red,blue,green,black" 

原型共享导致两个不同的对象调用的同一个数据

16、借用构造函数来实现继承

 

 
  1. function SuperType(){ 
  2. this.colors = ["red", "blue", "green"]; 
  3. } 
  4.  
  5. function SubType(){  
  6. //inherit from SuperType 
  7. SuperType.call(this); 
  8. } 
  9.  
  10. var instance1 = new SubType(); 
  11. instance1.colors.push("black"); 
  12. alert(instance1.colors); //"red,blue,green,black" 
  13.  
  14. var instance2 = new SubType(); 
  15. alert(instance2.colors); //"red,blue,green" 

传递参数

 

 
  1. function SuperType(name){ 
  2. this.name = name; 
  3. } 
  4.  
  5. function SubType(){  
  6. //inherit from SuperType passing in an argument 
  7. SuperType.call(this, "Nicholas"); 
  8.  
  9. //instance property 
  10. this.age = 29; 
  11. } 
  12.  
  13. var instance = new SubType(); 
  14. alert(instance.name); //"Nicholas"; 
  15. alert(instance.age); //29 

17、组合继承方式

 

 
  1. function SuperType(name){ 
  2. this.name = name; 
  3. this.colors = ["red", "blue", "green"]; 
  4. } 
  5.  
  6. SuperType.prototype.sayName = function(){ 
  7. alert(this.name); 
  8. }; 
  9.  
  10. function SubType(name, age){  
  11. SuperType.call(this, name); 
  12.  
  13. this.age = age; 
  14. } 

18、原型继承

 

 
  1. function object(o){ 
  2. function F(){} 
  3. F.prototype = o; 
  4. return new F(); 
  5. } 
  6.  
  7. var person = { 
  8. name: "Nicholas", 
  9. friends: ["Shelby", "Court", "Van"] 
  10. }; 
  11.  
  12. var anotherPerson = object(person); 
  13. anotherPerson.name = "Greg"; 
  14. anotherPerson.friends.push("Rob"); 

19、寄生组合式继承

 

 
  1. function object(o){ 
  2. function F(){} 
  3. F.prototype = o; 
  4. return new F(); 
  5. } 
  6.  
  7. function inheritPrototype(subType, superType){ 
  8. var prototype = object(superType.prototype); //create object 
  9. prototype.constructor = subType; //augment object 
  10. subType.prototype = prototype; //assign object 
  11. } 
  12.  
  13. function SuperType(name){ 
  14. this.name = name; 
  15. this.colors = ["red", "blue", "green"]; 
  16. } 
  17.  
  18. SuperType.prototype.sayName = function(){ 
  19. alert(this.name); 
  20. }; 
  21.  
  22. function SubType(name, age){  
  23. SuperType.call(this, name); 
  24.  
  25. this.age = age; 
  26. } 
  27.  
  28. inheritPrototype(SubType, SuperType); 
  29.  
  30. SubType.prototype.sayAge = function(){ 
  31. alert(this.age); 
  32. }; 
  33.  
  34. var instance1 = new SubType("Nicholas", 29); 
  35. instance1.colors.push("black"); 
  36. alert(instance1.colors); //"red,blue,green,black" 
  37. instance1.sayName(); //"Nicholas"; 
  38. instance1.sayAge(); //29 
  39.  
  40.  
  41. var instance2 = new SubType("Greg", 27); 
  42. alert(instance2.colors); //"red,blue,green" 
  43. instance2.sayName(); //"Greg"; 
  44. instance2.sayAge(); //27 

以上就是今天的javascript学习小结,之后每天还会继续更新,希望大家继续关注。


注:相关教程知识阅读请移步到JavaScript/Ajax教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选