Welcome 微信登录

首页 / 脚本样式 / JavaScript / 每天一篇javascript学习小结(面向对象编程)

1、面向对象的工厂方法

 function createPerson(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 person1 = createPerson("Nicholas", 29, "Software Engineer");var person2 = createPerson("Greg", 27, "Doctor");person1.sayName(); //"Nicholas"person2.sayName(); //"Greg"
工厂模型的方法的缺点是会产生大量重复代码!
2、构造函数模式创建对象

 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){alert(this.name); }; }var person1 = new Person("Nicholas", 29, "Software Engineer");var person2 = new Person("Greg", 27, "Doctor");person1.sayName(); //"Nicholas"person2.sayName(); //"Greg"alert(person1 instanceof Object); //truealert(person1 instanceof Person); //truealert(person2 instanceof Object); //truealert(person2 instanceof Person); //truealert(person1.constructor == Person); //truealert(person2.constructor == Person); //truealert(person1.sayName == person2.sayName); //false
 使用new关键字创建对象会经历以下四个过程
  • 1、创建一个新对象
  • 2、将构造函数的作用域赋给一个新对象(因此this就指向了这个新对象)
  • 3、执行构造函数的方法(为这个新对象赋值)
  • 4、返回新对象
3、将构造函数当函数用
 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){alert(this.name); };}var person = new Person("Nicholas", 29, "Software Engineer");person.sayName(); //"Nicholas"Person("Greg", 27, "Doctor"); //adds to windowwindow.sayName(); //"Greg"var o = new Object();Person.call(o, "Kristen", 25, "Nurse");o.sayName(); //"Kristen"
构造函数当做函数使用就和普通的函数没有任何不同,它属于window对象下面添加的方法而已。由于构造函数创建的对象实际上是创建一个新对象,因此在本质上两者还是不一样的,还是分离的,他们的方法还是不一样的!
4、将共有的方法方法全局解决不一致的问题

 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = sayName;}function sayName(){ alert(this.name);}var person1 = new Person("Nicholas", 29, "Software Engineer");var person2 = new Person("Greg", 27, "Doctor");person1.sayName(); //"Nicholas"person2.sayName(); //"Greg"alert(person1 instanceof Object); //truealert(person1 instanceof Person); //truealert(person2 instanceof Object); //truealert(person2 instanceof Person); //truealert(person1.constructor == Person); //truealert(person2.constructor == Person); //truealert(person1.sayName == person2.sayName); //true
虽然上面的方法解决了一致的问题,但是定义的全局的方法本身属于window,那么局部和全局就没有分开!所以这个方法使用的并不多见!也不建议使用。
5、原型模式
我们创建的任何的一个函数都有一个原型对象,这个属性是一个指针,它指向一个对象,而这个对象的作用是可以有特定的类型的所有的实例共享的方法!

 function Person(){}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.job = "Software Engineer";Person.prototype.sayName = function(){ alert(this.name);};var person1 = new Person();person1.sayName(); //"Nicholas"var person2 = new Person();person2.sayName(); //"Nicholas"alert(person1.sayName == person2.sayName); //truealert(Person.prototype.isPrototypeOf(person1)); //truealert(Person.prototype.isPrototypeOf(person2)); //true//only works if Object.getPrototypeOf() is availableif (Object.getPrototypeOf){ alert(Object.getPrototypeOf(person1) == Person.prototype); //true alert(Object.getPrototypeOf(person1).name); //"Nicholas"}
理解原型
无论什么时候只要是创建了一个函数,就会创建一个原型属性,这个属性指向函数的原型对象。在默认的情况下,原型对象都会包含一个constructor(构造函数属性),这个属性包含一个指向prototype属性所在函数的指针!
属性读取的顺序
每当代码读取某个对象的属性时候,都会执行一次搜索,目标是具有给定名字的属性,搜索从对象的实例本身开始查找,如有则返回,没有则继续搜索该对象的原型链,直至搜索到原型链的最外层!

 function Person(){}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.job = "Software Engineer";Person.prototype.sayName = function(){ alert(this.name);};var person1 = new Person();var person2 = new Person();person1.name = "Greg";alert(person1.name); //"Greg" 来自实例alert(person2.name); //"Nicholas" 来自原型
如果删除了这个元素的实例属性

function Person(){}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.job = "Software Engineer";Person.prototype.sayName = function(){ alert(this.name);};var person1 = new Person();var person2 = new Person();person1.name = "Greg";alert(person1.name); //"Greg" ?from instancealert(person2.name); //"Nicholas" ?from prototypedelete person1.name;alert(person1.name); //"Nicholas" - from the prototype
6、hasOwnProperty方法
这个方法可以检测一个属性是否存在于实例中,还是存在于原型中!hasOwnProperty是从Object继承来的,只要给定属性存在于对象实例中,才会返回true.

 function Person(){}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.job = "Software Engineer";Person.prototype.sayName = function(){alert(this.name);};var person1 = new Person();var person2 = new Person();alert(person1.hasOwnProperty("name")); //falsealert("name" in person1); //trueperson1.name = "Greg";alert(person1.name);//"Greg" ?from instancealert(person1.hasOwnProperty("name")); //truealert("name" in person1); //truealert(person2.name);//"Nicholas" ?from prototypealert(person2.hasOwnProperty("name")); //falsealert("name" in person2); //truedelete person1.name;alert(person1.name);//"Nicholas" - from the prototypealert(person1.hasOwnProperty("name")); //falsealert("name" in person1); //true
7、Object.keys() 可枚举属性方法
这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组

 function Person(){}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.job = "Software Engineer";Person.prototype.sayName = function(){alert(this.name);};var keys = Object.keys(Person.prototype);alert(keys);//"name,age,job,sayName"如果想得到所有实例的属性,无论它是否可以枚举都可以使用这个方法来获取 function Person(){}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.job = "Software Engineer";Person.prototype.sayName = function(){alert(this.name);};var keys = Object.getOwnPropertyNames(Person.prototype);alert(keys);//"constructor,name,age,job,sayName"
此方法高版本浏览器才支持
8、简单的原型写法

 function Person(){}Person.prototype = {name : "Nicholas",age : 29,job: "Software Engineer",sayName : function () {alert(this.name);}};var friend = new Person();alert(friend instanceof Object); //truealert(friend instanceof Person); //truealert(friend.constructor == Person); //falsealert(friend.constructor == Object); //true
重写了原型就等于将默认的原型方法覆盖,那么同样的构造方法也会被重写,重写的构造方法指向了Object对象!而不是原来的对象Person
如果还是想指向之前的构造方法,可以显示的指定

 function Person(){}Person.prototype = {constructor : Person,name : "Nicholas",age : 29,job: "Software Engineer",sayName : function () {alert(this.name);}};var friend = new Person();alert(friend instanceof Object); //truealert(friend instanceof Person); //truealert(friend.constructor == Person); //truealert(friend.constructor == Object); //false
9、原型方法的动态添加

function Person(){}Person.prototype = {constructor: Person,name : "Nicholas",age : 29,job : "Software Engineer",sayName : function () {alert(this.name);}};var friend = new Person();Person.prototype.sayHi = function(){alert("hi");};friend.sayHi();//"hi" ?works!
10、原生对象的原型方法

alert(typeof Array.prototype.sort); //"function"alert(typeof String.prototype.substring);//"function"String.prototype.startsWith = function (text) {//修改原生对象的原型方法return this.indexOf(text) == 0;};var msg = "Hello world!";alert(msg.startsWith("Hello"));//true
11、组合使用构造函数和原型模式创建对象

//构造函数模式function Person(name, age, job){this.name = name;this.age = age;this.job = job;this.friends = ["Shelby", "Court"];}//原型模式Person.prototype = {constructor: Person,sayName : function () {alert(this.name);}};var person1 = new Person("Nicholas", 29, "Software Engineer");var person2 = new Person("Greg", 27, "Doctor");person1.friends.push("Van");alert(person1.friends);//"Shelby,Court,Van"alert(person2.friends);//"Shelby,Court"alert(person1.friends === person2.friends); //falsealert(person1.sayName === person2.sayName); //true
12、动态原型模式

function Person(name, age, job){//propertiesthis.name = name;this.age = age;this.job = job;//methodsif (typeof this.sayName != "function"){Person.prototype.sayName = function(){alert(this.name);};}}var friend = new Person("Nicholas", 29, "Software Engineer");friend.sayName();
13、寄生构造函数模式

 function Person(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 friend = new Person("Nicholas", 29, "Software Engineer");friend.sayName(); //"Nicholas"function SpecialArray(){ //create the arrayvar values = new Array();//add the valuesvalues.push.apply(values, arguments);//assign the methodvalues.toPipedString = function(){return this.join("|");};//return itreturn values; }var colors = new SpecialArray("red", "blue", "green");alert(colors.toPipedString()); //"red|blue|green"alert(colors instanceof SpecialArray);
上诉方法有一点说明下,由于它是依赖外层对象来创建一个新对象,因此不能依赖 instanceof方法来确定属性和方法的来源!它实际上和构造函数的没有关系!
14、稳妥构造函数模式

 function Person(name, age, job){var o = new Object();o.sayName = function(){alert(name);};return o;}var friend = Person("Nicholas", 29, "Software Engineer");friend.sayName(); //"Nicholas"
此方法不依赖任何new this 关键符!如果要访问对象的方法和属性,只能通过对象已经定义好的方法来获取!
15、继承
javascript实现继承是通过原型链来实现的

function SuperType(){this.property = true;//定义一个属性}SuperType.prototype.getSuperValue = function(){//定义的原型方法return this.property;};function SubType(){this.subproperty = false;}//inherit from SuperTypeSubType.prototype = new SuperType();SubType.prototype.getSubValue = function (){return this.subproperty;};var instance = new SubType();alert(instance.getSuperValue());//truealert(instance instanceof Object); //truealert(instance instanceof SuperType);//truealert(instance instanceof SubType); //truealert(Object.prototype.isPrototypeOf(instance));//truealert(SuperType.prototype.isPrototypeOf(instance)); //truealert(SubType.prototype.isPrototypeOf(instance));//trueSubType继承SuperType的方法和属性,因此当instance可以直接调用SuperType的方法! function SuperType(){this.property = true;}SuperType.prototype.getSuperValue = function(){return this.property;};function SubType(){this.subproperty = false;}//inherit from SuperTypeSubType.prototype = new SuperType();//new methodSubType.prototype.getSubValue = function (){return this.subproperty;};//override existing methodSubType.prototype.getSuperValue = function (){return false;};var instance = new SubType();alert(instance.getSuperValue());//false
上面的例子说明,重写的原型会覆盖之前继承的原型,最后返回的往往不是预期的效果

 function SuperType(){this.property = true;}SuperType.prototype.getSuperValue = function(){return this.property;};function SubType(){this.subproperty = false;}//inherit from SuperTypeSubType.prototype = new SuperType();//使用字面量添加的方法导致上面的方法失效了SubType.prototype = {getSubValue : function (){return this.subproperty;},someOtherMethod : function (){return false;}}; var instance = new SubType();console.log(instance);alert(instance.getSuperValue());//error!
下面的例子也说明重写原型带来的风险

 function SuperType(){this.colors = ["red", "blue", "green"];}function SubType(){}//inherit from SuperTypeSubType.prototype = new SuperType();var instance1 = new SubType();instance1.colors.push("black");alert(instance1.colors);//"red,blue,green,black"var instance2 = new SubType();alert(instance2.colors);//"red,blue,green,black"
原型共享导致两个不同的对象调用的同一个数据
16、借用构造函数来实现继承

 function SuperType(){this.colors = ["red", "blue", "green"];}function SubType(){ //inherit from SuperTypeSuperType.call(this);}var instance1 = new SubType();instance1.colors.push("black");alert(instance1.colors);//"red,blue,green,black"var instance2 = new SubType();alert(instance2.colors);//"red,blue,green"
传递参数

 function SuperType(name){this.name = name;}function SubType(){ //inherit from SuperType passing in an argumentSuperType.call(this, "Nicholas");//instance propertythis.age = 29;}var instance = new SubType();alert(instance.name);//"Nicholas";alert(instance.age); //29
17、组合继承方式

function SuperType(name){this.name = name;this.colors = ["red", "blue", "green"];}SuperType.prototype.sayName = function(){alert(this.name);};function SubType(name, age){ SuperType.call(this, name);this.age = age;}
18、原型继承

 function object(o){function F(){}F.prototype = o;return new F();}var person = {name: "Nicholas",friends: ["Shelby", "Court", "Van"]};var anotherPerson = object(person);anotherPerson.name = "Greg";anotherPerson.friends.push("Rob");
19、寄生组合式继承

 function object(o){function F(){}F.prototype = o;return new F();}function inheritPrototype(subType, superType){var prototype = object(superType.prototype);//create objectprototype.constructor = subType;//augment objectsubType.prototype = prototype; //assign object}function SuperType(name){this.name = name;this.colors = ["red", "blue", "green"];}SuperType.prototype.sayName = function(){alert(this.name);};function SubType(name, age){ SuperType.call(this, name);this.age = age;}inheritPrototype(SubType, SuperType);SubType.prototype.sayAge = function(){alert(this.age);};var instance1 = new SubType("Nicholas", 29);instance1.colors.push("black");alert(instance1.colors); //"red,blue,green,black"instance1.sayName(); //"Nicholas";instance1.sayAge();//29var instance2 = new SubType("Greg", 27);alert(instance2.colors); //"red,blue,green"instance2.sayName(); //"Greg";instance2.sayAge();//27
以上就是今天的javascript学习小结,之后每天还会继续更新,希望大家继续关注。