AI智能
改变未来

理解JavaScript中的面向对象


理解JavaScript中的面向对象

1、工厂模式:用函数来封装,以特定接口创建对象的细节

  1. 解决了创建多个相似对象的问题,
  2. 多用于创建多个含有相同属性,和方法的对象,避免代码的重复编写;
  3. 没有解决对象识别的问题(即怎么知道一个对象的类型)(它的 instanceof 只能是Object)
function creatPerson(name,age,job) {var o = new Object();o.name= name;o.age= age;o.job= job;o.sayName = function(){alert(this.name);};return o;}var p1 = creatPerson(\"hh\",23,\"worker\");var p2 = creatPerson(\"xx\",26,\"worker1\");p1.__proto__===p2.__proto__===Object.prototype;

2、构造函数模式:

缺点:每个方法都在每个实例上重新创建了一例子中p1.sayName!=p2.sayName。

function Person(name,age,job){this.age = age;this.name = name;this.job = job;this.sayName = function(){alert(this.name)}//this.sayName = sayName;   //解决方式}var p1 = new Person(\"hh\",23,\"worker\");var p2 = new Person(\"xx\",26,\"worker1\");//function sayName(){alert(this.name)}  //解决方式new的执行:{var obj ={};obj.__proto__ = Person.prototype;Person.call(obj);return obj}p1 instanceof Person //true;p2 instanceof Person //true;p1 instanceof Object //true;p2 instanceof Object //true;这样是得p1和p2实例有了特定的类型, Person;

3、 原型模式

  1. 优点:他省略了构造函数初始化参数这个环节,原型中所有属性都被很多实例共享,共享对函数非常合适,基本属性也还行
    通过在实例上添加同名属性,可隐藏原型中的对应属性值;
  2. 缺点: 他的共享属性,对于包含引用类型值的属性 如果实例重新赋值没什么影响,和基本类型一样,如果是操作修改 就有些问题了,会使得所有实例获取到的该属性都被修改, 所以也不单独使用
function Person(){}Person.prototype={constructor:Person,name:\"ss\",friends:[\"s1\",\"s2\"],sayName:function(){alert(this.name)}}var p1= new Person();var p2= new Person();p1.name = \"p1\"console.log(p1.name) //p1console.log(p2.name) //ssp1.friends.push(\"s3\");console.log(p1.friends) //[\"s1\",\"s2\",\"s3\"]console.log(p2.friends) //[\"s1\",\"s2\",\"s3\"]

继承
1、组合继承:(常用继承模式)

  1. 这样可以使得实例分别拥有各自的属性(包括引用类型的,实例间互补影响),又可以使用相同的方法;
  2. 缺陷: 无论什么情况下,都会调用两次父类的构造函数
function Father(){this.name =\"ss\";this.friends=[1,2,3,4]}function Son(){Father.call(this);}Son.prototype = new Father(); // Son 原型获得Father上的属性,name和friendsvar son1 = new Son(); // 此时调用Son构造函数为son1 实例上添加了属性(name和friends), 这些属性就屏蔽了原型中的同名属性;// 调用两次Father构造函数的结果就是有两组属性,一组在实例上,一组在原型上;

2、寄生组合式:(理想的继承实现方式)

  1. 解决组合继承中的缺陷,生成两组属性,只在实例上生成原型;
  2. 通过构造函数来继承属性,通过原型链的混成形式来继承方法(就是给子类原型,指定一个父类的副本即可)
function inherit(son,father){var prototype = object(father.prototype);// 上句话,创建父类原型的副本,prototype.__proto__ = Father.prototype;// prototype 继承constructor prototype.constructor 取的是原型链上,原型的Father.prototype.constructor, 为 Father();即:prototype.constructor == prototype.__proto__.constructor  // true// prototype.hasOwnPrototyoe(\"constructor\") //falseprototype.constructor = son; // 弥补重写原型造成的默认属性的修改;//此时是给prototype 添加了constructor 属性,赋值为son, 屏蔽了原型上的constructor属性// prototype.hasOwnPrototype(\"constructor\") // true// prototype.constructor = son;// prototype.__proto__.constructor = fatherson.prototype  = prototype;// 给子类原型赋值为父类原型的副本;}//使用:function Father(){this.name=\"11\";this.age=12;}Father.prototype.sayName=function(){alert(this.name);}function Son(){Father.call(this);this.age=23;}inherit(Son,Father);Son.prototype.sayAge=function(){alert(this.age)}

参考阅读

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 理解JavaScript中的面向对象