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); //true
alert(person1 instanceof Person); //true
alert(person2 instanceof Object); //true
alert(person2 instanceof Person); //true alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true alert(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 window
window.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); //true
alert(person1 instanceof Person); //true
alert(person2 instanceof Object); //true
alert(person2 instanceof Person); //true alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true alert(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); //true alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true //only works if Object.getPrototypeOf() is available
if (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 instance
alert(person2.name); //"Nicholas" ?from prototype delete 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")); //false
alert("name" in person1); //true person1.name = "Greg";
alert(person1.name); //"Greg" ?from instance
alert(person1.hasOwnProperty("name")); //true
alert("name" in person1); //true alert(person2.name); //"Nicholas" ?from prototype
alert(person2.hasOwnProperty("name")); //false
alert("name" in person2); //true delete person1.name;
alert(person1.name); //"Nicholas" - from the prototype
alert(person1.hasOwnProperty("name")); //false
alert("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); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false
alert(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); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //true
alert(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); //false
alert(person1.sayName === person2.sayName); //true
12、动态原型模式
function Person(name, age, job){ //properties
this.name = name;
this.age = age;
this.job = job; //methods
if (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 array
var values = new Array(); //add the values
values.push.apply(values, arguments); //assign the method
values.toPipedString = function(){
return this.join("|");
}; //return it
return 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 SuperType
SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function (){
return this.subproperty;
}; var instance = new SubType();
alert(instance.getSuperValue()); //true alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true
SubType继承SuperType的方法和属性,因此当instance可以直接调用SuperType的方法!
function SuperType(){
this.property = true;
} SuperType.prototype.getSuperValue = function(){
return this.property;
}; function SubType(){
this.subproperty = false;
} //inherit from SuperType
SubType.prototype = new SuperType(); //new method
SubType.prototype.getSubValue = function (){
return this.subproperty;
}; //override existing method
SubType.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 SuperType
SubType.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 SuperType
SubType.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 SuperType
SuperType.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 argument
SuperType.call(this, "Nicholas"); //instance property
this.age = 29;
} var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //
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 object
prototype.constructor = subType; //augment object
subType.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(); // var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //
javascript 学习总结(九)面向对象编程的更多相关文章
- javascript 学习笔记之面向对象编程(一):类的实现
~~想是一回事,做是一回事,写出来又是一回事~~一直以来,从事C++更多的是VC++多一些,从面向过程到面向对象的转变,让我对OO的编程思想有些偏爱,将一个客观存在的规律抽象出来总是让人比较兴奋,通过 ...
- javascript 学习笔记之面向对象编程(二):继承&多态
~~接上篇~~上一篇实现了类的实现以及类成员变量和方法的定义,下面我们来了解下面向对象中两个最重要的特性:继承和多态. 继承 js中同样可以实现类的继承这一面向对象特性,继承父类中的所有成员(变量和属 ...
- JavaScript基础入门12 - 面向对象编程
目录 JavaScript 面向对象编程 前言 构造函数创建对象 instanceof constructor 返回值 原型对象 关于对象的属性查找 in hasOwnProperty() JS当中实 ...
- 简单介绍Javascript匿名函数和面向对象编程
忙里偷闲,简单介绍一下Javascript中匿名函数和闭包函数以及面向对象编程.首先简单介绍一下Javascript中的密名函数. 在Javascript中函数有以下3中定义方式: 1.最常用的定义方 ...
- JavaSE学习笔记05面向对象编程01
面向对象编程01 java的核心思想就是OOP 面向过程&面向对象 面向过程思想: 步骤清晰简单,第一步做什么,第二步做什么...... 面向过程适合处理一些较为简单的问题 面向对象思想: 物 ...
- python 学习笔记7 面向对象编程
一.概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." ...
- C++ Primer 学习笔记_67_面向对象编程 --转换与继承、复制控制与继承
面向对象编程 --转换与继承.复制控制与继承 I.转换与继承 引言: 由于每一个派生类对象都包括一个基类部分,因此能够像使用基类对象一样在派生类对象上执行操作. 对于指针/引用,能够将派生类对象的指针 ...
- C++ Primer 学习笔记_69_面向对象编程 --继承情况下的类作用域
面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:假设不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这样的类作用域的层次嵌套使 ...
- Spark学习笔记11面向对象编程
面向对象编程 11.1 object类 11.1.1定义一个简单的类 11.1.2 field的getter与setter 定义类包含,定义类的field及方法.其格式如下 class Cla ...
- C++ Primer 学习笔记_72_面向对象编程 --句柄类与继承[续]
面向对象编程 --句柄类与继承[续] 三.句柄的使用 使用Sales_item对象能够更easy地编写书店应用程序.代码将不必管理Item_base对象的指针,但仍然能够获得通过Sales_item对 ...
随机推荐
- Hadoop Streaming 得到mapreduce_map_input_file中遇到的问题的版本号
1.Hadoop Streaming,您可以在任务获得hadoop设置环境变量, 例如,使用awk书面map从而能获得:filename = ENVIRON["mapreduce_map_i ...
- JavaScript之包装对象
JavaScript对象是一种复合值:它是属性和已命名值的集合.通过"."符号来引用属性值.当属性值是一个函数时,称为方法. ①一段你常用但却未必明白其真正底层原理的代码: var ...
- PHP Yii框架开发——组织架构网站重构
最近一段时间在维护公司的组织架构网站(Org),旧版网站只是用了xampp简单搭建了一套环境部署在了windows机器上,代码结构相对简单. 整个架构如下: 整个架构没有用到复杂的结构,class里放 ...
- RabbitMQ (两)工作队列
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/37620057 本系列教程主要来自于官网新手教程的翻译,然后自己进行了部分的改动与 ...
- jsp 行动标签
jsp行动标签 签.它影响JSP执行时的功能. 1.include动作标签 <jsp:include page="文件名称字"/> 或 <jsp:include ...
- JS日期时间选择器
本文介绍一种日期和时间选择器的使用方法.此选择器由jqueryUI实现,支持精确到毫秒的时间选择. 此选择器项目地址为http://trentrichardson.com/examples/timep ...
- hdu4864Task(馋)
主题链接: 啊哈哈.点我 题目: Task Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- oracle_连接数_查看
查看oracle数据库的连接数以及用户 .查询oracle的连接数 select count(*) from v$session; .查询oracle的并发连接数 select count(*) ...
- 64bit Centos6.4编hadoop-2.5.1
64bit Centos6.4编hadoop-2.5.1 1.说明 a) 因为从apache下载下来的tar.gz包是用32 bit编译的,全部假设用Linux 64作为hadoop的 ...
- Codeforces Round #235 (Div. 2) D. Roman and Numbers(如压力dp)
Roman and Numbers time limit per test 4 seconds memory limit per test 512 megabytes input standard i ...