javascript——面向对象程序设计(2)
<script type="text/javascript">
//1、理解原型对象
//2、原型与in操作符
//3、更简单的原型语法
//4、原型的动态性
//5、原生对象原型
//6、原型对象的问题 //1、无论什么时候,只要创建了一个函数,就会根据一组特定的规则,为该函数创建一个prototype属性,该属性指向函数的原型对象
//在默认情况下,所有的原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针
//如
function Person(){ }
//Person.prototype.constructor 指向Person
//创建了自定义的构造函数之后,其原型对象默认只会取得constructor属性,至于其他方法则都是从Object继承而来
//当调用函数的创建一个新实例之后,该实例的内部包含一个指针(内部属性)指向构造函数的原型对象
//在Firefox、safari、chrome在每个对象上都支持一个属性_proto_访问
var p1=new Person();
alert(Person.prototype.isPrototypeOf(p1)) alert(Object.getPrototypeOf(p1)==Person.prototype) //虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们在实例中添加了一个属性
//而该属性的名称与原型的中的实例同名,那我们就在实例中创建该属性,该属性将会屏蔽原型中的那个属性。eg:
function Person() {
}
Person.prototype.name="amber";
Person.prototype.age=23;
Person.prototype.job="software engineer";
Person.prototype.sayName=function(){
alert(this.name)
} var person1=new Person();
var person2=new Person();
person1.name="amber.Xu";
alert(person1.name);//amber.xu --来自实例
alert(person2.name);//amber --来自原型 delete person1.name;
alert(person1.name);//amber --来自原型 //使用hasOwnProperty()方法可以检测一个属性是存在于实例中还是存在于原型中,这个方法(从Object继承而来)
//只在给定属性存在于对象实例中时,才会返回true
function Person() {
}
Person.prototype.name="amber";
Person.prototype.age=23;
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(person2.hasOwnProperty("name"));//false 来自实例 person1.name="amber.xu";
alert(person1.name);
alert(person1.hasOwnProperty("name"));//true 来自实例 delete person1.name;
alert(person1.name);
alert(person1.hasOwnProperty("name"));//false 来自原型 //2、原型与in操作符
//in 有两种使用方式,一个是的单独使用和在for-in 中使用。在单独使用时,in操作符会在对象能够访问给定属性时返回true
//无论该属性时来自原型还是实例
function Person() {
}
Person.prototype.name="amber";
Person.prototype.age=23;
Person.prototype.job="software engineer";
Person.prototype.sayName=function(){
alert(this.name)
}
var person1=new Person();
var person2=new Person();
alert("name" in person1);//true 来自原型
alert("name" in person2);//true 来自原型
alert("height" in person1);//false //这样就可以封装一个函数(给定属性是否是来给定对象的原型)
function hasPrototypeProperty(object,name){
return !object.hasOwnProperty(name) && (name in object);
}
alert("----------------------------------");
alert(hasPrototypeProperty(person1,"name"));//true person1.name="张三";
alert(hasPrototypeProperty(person1,"name"));//false //使用for-in 返回的是所有能够通过对象访问、可枚举的属性,其中既包含原型属性也包含实例属性。
//屏蔽了原型中不可枚举属性(将Enumerable标记为false的属性)的实例属性也会在for-in中返回
//ie早期版本总中有一个bug:屏蔽了原型中不可枚举属性的实例属性也不会在for-in中返回
//eg:
var o={
toString:function(){
return "my object";
}
}; for(var prop in o){
if(prop=="toString"){
alert("找到了");//在ie早期版本中不会显示
}
} //要取得对象上所有可枚举的属性,可以使用ECMAScript5的Object.keys()方法。接受一个对象作为参数,
//包含所有可枚举属性的字符串数组
function Person() {
}
Person.prototype.name="amber";
Person.prototype.age=23;
Person.prototype.job="software engineer";
Person.prototype.sayName=function(){
alert(this.name)
}
var person1=new Person();
var person2=new Person();
var keys=Object.keys(Person.prototype);
alert(keys) person1.name="amber.Xu";
person1.age=23;
var keys=Object.keys(person1);
alert(keys) alert("-----------------------------------------")
//如果想要得到所有的实例属性不管他是否可以枚举,都可以使用
alert(Object.getOwnPropertyNames(person1));
alert(Object.getOwnPropertyNames(Person.prototype)); alert("更简单的原型语法-----------------------------------------")
//3、更简单的原型语法
function Person() { } Person.prototype={
name:"AMBER",
age:23,
job:"software",
sayName:function(){
alert(this.name)
}
} //这样写之后constructor属性不再指向Person函数,而是指向Object构造函数。
//尽管通过instanceof操作符还能返回正确的结果,但是通过constructor已经无法确定对象的类型了,eg:
var friend=new Person();
alert(friend instanceof Person)//true
alert(friend instanceof Object)//true
alert(friend.constructor==Person);//false
alert(friend.constructor==Object);//true
//如果constructor对你真的很重要,可以向下面一样设置成适当的值 function Person() { } Person.prototype={
constructor:Person,
name:"AMBER",
age:23,
job:"software",
sayName:function(){
alert(this.name)
}
}
var friend=new Person();
alert("手动设置constructor-----------------------------------------")
alert(friend.constructor==Person);//true //这种手动的添加了constructor会使constructor变成可枚举的元(原生的constructor属性时不可枚举的)。
//这种情况下就可以使用
Object.defineProperty(Person.prototype,"constructor",{
enumerable:false,
value:Person
}); //原型的动态性
var friend=new Person();
Person.prototype.sayHi=function(){
alert("Hi");
} friend.sayHi();//Hi (正常执行)
//因为实例和原型之间是松散的连接关系,实例与原型之间的连接只不过是一个指针,而非副本
//当我们调用sayHi()方法时,首先会在实例中搜索名为sayHi的方法,在没找到的情况下会搜索原型。 //但是,如果是重写整个原型对象,那么情况就不一样了。
//我们知道,调用构造函数时会为实例添加一个指向最初原型的Prototype指针,而把原型修改为另一个对象就等于切断了构造函数与最初原型之间的联系。
//请记住:实例中的指针仅指向原型,而不指向构造函数。eg:
function A(){}
var a1=new A();
A.prototype={
constructor:A,
name:"AMBER",
age:23,
job:"software",
sayName:function(){
alert(this.name)
}
}
alert("ERROR-------------------------------------");
alert(a1.sayName());
//我们创建了一个A的实例,然后又重写了其原型对象,然后在调用a1.sayName()发生了错误,因为a指向的原型中不包含以该名字命名的属性/方法 //原生对象的原型
//原型模式的重要性不仅体现在创建自定义类型方面。就连所有的原生的引用类型,都是采用这种模式创建的。所有的原生引用类型
//都在其构造函数的原型上定义的方法 eg:
alert(typeof Array.prototype.sort);//function
alert(typeof String.prototype.substring);//function
//不仅可以在原生对象的原型取得虽有默认方法的引用,而且可以定义新的方法
//为String类型添加一个startsWith()的方法
String.prototype.startsWith=function(text){
return this.indexOf(text) == 0;
};
var msg="Hello";
alert(msg.startsWith("H")); //我们并不建议这样做。 alert("原型对象的问题");
//6、原型对象的问题 实例
function Ques() {
} Ques.prototype={
constructor:Ques,
name:"amber",
age:23,
job:"IT",
friends:["张三","李四"],//引用类型
sayName:function(){
alert(this.name)
}
}; var q1=new Ques();
var q2=new Ques();
q1.friends.push("王五");
alert(q1.friends);//
alert(q2.friends);//
alert(q1.friends===q2.friends);
//相信大家已经看到了问题,当我创建了两个实例q1、q2,当我为q1的“朋友”添加了“王五”之后,q2的”朋友“也有了三个张三、李四、王五
//那是因为数组存在于Ques.prototype上,而非q1上。所以出现了如上结果。 //而正是这个问题,我们很少看到有人单独使用原型模式的原因所在。
</script>
javascript——面向对象程序设计(2)的更多相关文章
- JavaScript 面向对象程序设计(下)——继承与多态 【转】
JavaScript 面向对象程序设计(下)--继承与多态 前面我们讨论了如何在 JavaScript 语言中实现对私有实例成员.公有实例成员.私有静态成员.公有静态成员和静态类的封装.这次我们来讨论 ...
- JavaScript面向对象程序设计:数组
或许你会奇怪,面向对象的程序设计为什么从数组开始讲起?这是因为……其间的种种关系吧……嘿嘿,这里先卖个关子,先来看看我们熟悉的数组在JavaScript里面是什么样子的. 1. 创建数组 在J ...
- javascript面向对象程序设计系列(一)---创建对象
javascript是一种基于对象的语言,但它没有类的概念,所以又和实际面向对象的语言有区别,面向对象是javascript中的难点之一.现在就我所理解的总结一下,便于以后复习: 一.创建对象 1.创 ...
- [TimLinux] JavaScript 面向对象程序设计
1. 面向对象 面向对象语言有一个标志:都有类的概念.通过类可以创建任意多个具有相同属性和方法的对象.ECMAScript中没有类的概念,因此JavaScript中的对象夜雨基于类的语言中的面向对象有 ...
- javascript——面向对象程序设计(4)
<script type="text/javascript"> //1.继承 //2.原型链 //3.借用构造函数 //4.组合继承 //5.原型式继承 //6.寄生式 ...
- javascript——面向对象程序设计(3)
<script type="text/javascript"> //1.结合使用构造函数模式和原型模式 //2.动态原型模式 //3.寄生构造函数模式 //4.稳妥构造 ...
- javascript——面向对象程序设计(1)
<script type="text/javascript"> //ECMA-262把对象定义为:“无序属性的 集合,其属性可以包含基本值.对象或者函数” //理解对象 ...
- javascript面向对象程序设计
在学习js面向对象编程之前,首先须要知道什么是面向对象.面向对象语言都有类的概念,通过它能够创建具有同样属性和方法的对象.但js并没有类的概念,因此js中的对象和其它语言的对象有所不同. js对象能够 ...
- javascript 面向对象程序设计--深刻理解对象
javascript中,每个对象都是基于一个引用类型创建的,我们可以把ECMAScript 的对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数. 深刻理解对象 创建自定义对象的最简单方式就 ...
随机推荐
- Google Map API 学习三
- asp.net生成二维码的方法
asp.net生成二维码的方法 [复制链接] 这个要利用一个Dll文件. 如下 Gma.QrCodeNet.Encoding.dll (105.5 KB, 下载次数: 27) 当然大家也可以直 ...
- (转载)linux中shell变量
(转载)http://blog.csdn.net/zahuopuboss/article/details/8633891 为使shell编程更有效,系统提供了一些shell变量.shell变量可以保存 ...
- OC语言中类目,延展,协议
一.类目 指向已知的类中添加新方法,不破坏封装性.已知类可以是自定义的类和系统的类. 1.类目的实现和声明 建一个学生类,并增加类目 (1).声明(是在Student+Working.h中) 必须引入 ...
- ACM1720_A+Bcoming(进制转换的新思路)——代码超少哟!
using namespace std; int main() { int a,b; while(cin>>hex>>a>>b) { cout<<dec ...
- Hibernate 以流的方式获取数据
hibernateQuery.setFetchSize(Integer.MIN_VALUE); results = hibernateQuery.scroll(ScrollMode.FORWARD_O ...
- [MIREX] MIREX评测介绍
MIREX作为国际最权威音频检索评测大赛,竟然在百度上找不到任何介绍,只有几个与什么搜狗.腾讯获得什么成绩相关的检索内容,相比而言,TRECVID的内容收到重视多了...由于研究生阶段主要研究音频领域 ...
- [置顶] [MATLAB技术贴]漫谈MATLAB矩阵转置
矩阵转置是matlab最基本的操作了,但这个基本操作,也是很多初学者容易出现问题的地方.本帖通过几个实例演示matlab矩阵转置的操作. 方法一:' 运算符与 .' 运算符 >>a ...
- MySQL可视化管理工具 —— Navicat for MysSQL
类似PL/SQL管理Oracle的工具 Navicat可以管理MySQL 1.安装 2.连接(输入IP.端口.用户名.密码) 3.新建sql语句:点击左侧database.点击菜单“查询”.点击“新建 ...
- c#委托和事件(上)
C# 中的委托和事件 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真 ...