面向对象-原型对象

创建对象

Js中可以用构造函数模式创建对象,如:

    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, "aa");var person2 = new Person("YU", 29, "BB");

这里应注意函数名首字母应大写,按照约定,构造函数始终都应该以一个大写字母开头,而非构造函数则应以一个小写字母开头。

原型对象

上述方法中,有一个缺点,就是对象中的sayName方法,每次都会重新new一个对象,因此,也就是说不同对象的sayName方法地址是不同的,然而这个方法都只是执行提示姓名,这种创建两个相同的function,完成同样的任务,确实没有必要。所以这存在了缺陷。使用下面的方法可以避免这种缺陷。

    

 function Person() {}Person.prototype.name = "YuKaifei";Person.prototype.age = 25;Person.prototype.job = "SoftWare";Person.prototype.sayName = function () {alert(this.name);}var person1 = new Person();person1.sayName();//YuKaifeivar person2 = new Person();person2.sayName();  //YuKaifei
alert(person1.sayName == person2.sayName); //true

 

理解原型对象

函数

Person

prototype

指向所对应的原型对象

 

函数的原型对象

Person  Prototype  (person的原型对象)

constructor

指向所对应函数(person)的指针

Name

“YuKaiFei”

Age

25

Job

“Soft Ware”

sayName

(function)

 

自定义函数1

Person1

prototype

指向所对应的原型对象

 

自定义函数2

Person2

prototype

指向所对应的原型对象

 

无论什么时候,只要创建了一个新函数,就会为该函数创建一个prototype属性,这个属性就指向所对应的原型对象。而默认情况下,原型对象的constructor属性会指向所对应函数的地址。也就是说这时这两个对象各有一个属性,是存放对方的地址的。

当调用一个构造函数创建一个新实例之后,该函数内部也有一个属性prototype,这个属性是执行原型对象的地址。也就是说新实例其实与构造函数并没有直接关系。

需要注意的是,新实例虽然没有属性和方法,但是却可以通过查找对象属性的方式来调用原型对象中的属性和方法。

 

当新的实例创建新的属性之后,如果和原型对象是相同的属性,那么在下次调用时会调用新实例的属性,而不是原型对象的属性。如:

        var person1 = new Person();person1.name="aaaa";var person2 = new Person();alert(person1.name);//aaaa
alert(person2.name);//YuKaifei

 

in 操作符

有两种方式可以使用in,一种是单独in,一种是for-in,需要注意的是,无论该属性是存在于实例中还是存在于原型中,只要存在,就返回true。

例如 alert(name in person1)  返回true

for (var prop in person1) {if (prop == "name") {alert("name")}}

 

判断该属性是否存在实例中的方式是hasOwnPropery()方法。

例如:person1.hasOwnProperty(“Name”) 返回true

         Person2.hasOwnProperty(“Name”) 返回false

 

获取对象上所有可枚举的实例属性:

 var keys = Object.keys(Person.prototype);alert(keys); //name,age,job,syName,注意keys是一个数组。

更简单的原型语法—存在缺陷

Person.prototype = {name: "Nicholas",age: 29,jon: "SowfWare",syaName: function () {alert(this.name);}}

可以使用这种方法更简单的创建原型,但需要注意的是,这种写法相当于重写了原型对象,所有consturctor属性是新的,即不在指向person。如:

function Person() {}var friend = new Person();Person.prototype = {name: "Nicholas",age: 29,jon: "SowfWare",syaName: function () {alert(this.name);}}friend.sayName(); //error

 

上面代码会报错,原因在与重写了原型对象,指向丢失,也就是切断了现有原型与之前已经存在的对象之间的联系。如果避免这种方法可以在声明原型中指定: constructor:Person

原生对象的原型—String、Array

原型的模式体现在所有原生的引用类型,例如object、array、string等,都在其构造函数的原型上定义了方法,例如在Array.prototype中可以找到sort()方法,在string.prototype可以找到substring()方法。

通过原生对象的原型,不仅可以获得所有默认方法的引用,也可以随意的修改原生对象的原型,因此可以随时添加方法。例如:

为String添加一个名为startsWith() 方法。

String.prototype.startsWith = function (text) {return this.indexOf(text) == 0;}var msg = "Hello world!";alert(msg.startsWith("Hello")); //true

优化原型对象的缺陷

原型对象为了省略函数传递初始化这一环节,结果所有的实例在默认情况下都会取得相同的值,这对于值类型属性共享还可以,但是对于引用类型则会存在问题。如:

 

function Person() {}Person.prototype = {name: "Nicholas",age: 29,jon: "SowfWare",friends:["Yu","Kai"],syaName: function () {alert(this.name);}}var person1 = new Person;person1.name = "yy";var person2 = new Person;
alert(person1.name);
//yy alert(person2.name); //Nicholas person1.friends.push("Fei");alert(person1.friends); //YuKaiFei alert(person2.friends); //YuKaiFei

可以看到值类型并没有什么影响,但因为引用类型的特殊,所有实例的值都将会被改变。

所有最好采用动态原型模式

动态原型模式-声明原型的推荐方式

 function Person(name, age, job) {this.name = name;this.age = age;this.job = job;this.friends = ["Yu", "kai"];if (typeof  this.sayName != "function") {this.sayName = function () {alert(this.name);};}}var f1 = new Person("Y", 29, "s");var f2 = new Person("Y", 29, "s");f1.friends.push("Fei");alert(f1.friends); //yu,kai,fei
alert(f2.friends);//yu,kai

 

转载于:https://www.cnblogs.com/y8932809/p/5386925.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374855.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

索引类型

1.B树索引 在Oracle中是通用索引,是创建索引时的默认索引。B树索引可以是单列索引,也可以是组合/复合索引。B树索引最多可以包括22列。 2.位图索引 位图索引时决策支持系统(DSS)和数据仓库的理想选择,它们不应该用于事…

C语言条件运算符

先看一个error error: lvalue required as left operand of assignment| i 0 ? X 1.0 : X * x;修改后 i 0 ? (X 1.0) : (X * x);也就是说条件运算符可以执行语句,当是赋值语句时要加括号规定优先级,不然会干扰程序判断。 因为条件运算符作为三目…

EJB 3.0注入和查找简介

介绍 Enterprise JavaBeans Specification v。3.0引入了简化的,基于注释的API,用于EJB注入和查找。 EJB 3.0现在是POJO,可以使用简单的注释将其注入其他组件(例如EJB和Servlet)。 EJB 3.0是Java EE 6的许多其他基于POJ…

SignalR + MVC5 简单示例

SignalR MVC5 简单示例 原文:SignalR MVC5 简单示例本文和前一篇文章很类似,只不过是把 SignalR 应用在了 MVC 中 新建项目,选择 MVC 模板 安装 SignalR Install-Package Microsoft.AspNet.SignalR 在项目中添加文件夹 Hubs 在 Hubs 文件夹中添加 Sign…

Java内存模型–快速概述和注意事项

在计算中, 内存模型描述了线程如何通过内存进行交互,或更一般地,它指定了为分段内存或分页内存平台生成代码时允许编译器进行的假设。 在给定程序和该程序的执行跟踪的情况下,它实质上描述了执行跟踪是否是该程序的合法执行。 Jav…

6-7 统计某类完全平方数 (20 分)

本题要求实现一个函数,判断任一给定整数N是否满足条件:它是完全平方数,又至少有两位数字相同,如144、676等。 函数接口定义: int IsTheNumber ( const int N );其中N是用户传入的参数。如果N满足条件,则该…

C#中数组、ArrayList和List三者的区别(转) ,加修改

在C#中数组&#xff0c;ArrayList&#xff0c;List都能够存储一组对象&#xff0c;那么这三者到底有什么样的区别呢。 数组 数组在C#中最早出现的。在内存中是连续存储的&#xff0c;所以它的索引速度非常快&#xff0c;而且赋值与修改元素也很简单。 <span style"font…

phpmyadmin mysql Access denied for user 'root'@'localhost'问题解决

centos6.4 32位的vps上装了lnmp以后&#xff0c;phpmyadmin无法连接mysql服务器&#xff0c;ssh命令行里mysql -uroot -p 命令后老是出现拒绝连接的情况。php程序里也是拒绝连接。尝试过修改phpmyadmin的config.inc.php文件&#xff0c;尝试过修改my.cnf文件&#xff0c;尝试过…

带有Spring和Maven教程的JAX–WS

Spring框架通过JAX-WS提供对Web服务的远程支持&#xff0c;实际上&#xff0c;如Spring 参考文档中所述 &#xff0c;有三种将Spring POJO服务公开为JAX-WS Web服务的方式&#xff1a; 公开基于Servlet的Web服务&#xff08;适用于Java EE 5环境&#xff09; 导出独立的Web服…

7-2 然后是几点 (15 分)

7-2 然后是几点 (15 分) 有时候人们用四位数字表示一个时间&#xff0c;比如 1106 表示 11 点零 6 分。现在&#xff0c;你的程序要根据起始时间和流逝的时间计算出终止时间。 读入两个数字&#xff0c;第一个数字以这样的四位数字表示当前时间&#xff0c;第二个数字表示分钟…

CXF学习(2) helloworld

0.新建一个项目取名wsserver. pom.xml 文件如下 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd…

Hive 接口介绍(Web UI/JDBC)

Hive 接口介绍&#xff08;Web UI/JDBC&#xff09; 实验简介 本次实验学习 Hive 的两种接口&#xff1a;Web UI 以及 JDBC。 一、实验环境说明 1. 环境登录 无需密码自动登录&#xff0c;系统用户名shiyanlou&#xff0c;密码shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubu…

Java最佳实践– Char到Byte和Byte到Char的转换

在使用Java编程语言时&#xff0c;我们将继续讨论与建议的实践有关的系列文章&#xff0c;我们将讨论String性能调优。 特别是&#xff0c;我们将重点介绍使用默认编码时如何有效地处理字符到字节和字节到字符的转换。 本文总结了两种提议的自定义方法与两种经典方法&#xff0…

IOS-C文件的创建于初始化函数.void init() write_file()

//文件初始化 void init(){ FILE * fpNULL; fpfopen("telbook.data", "rb"); int count0; if (fpNULL) //没有这个文件就把这个文件创建出来 { fpfopen("tellbook.data", "wb"); fwrite(&count, sizeof(count), 1, fp); fclose(…

7-3 逆序的三位数 (10 分)

7-3 逆序的三位数 (10 分) 程序每次读入一个正3位数&#xff0c;然后输出按位逆序的数字。注意&#xff1a;当输入的数字含有结尾的0时&#xff0c;输出不应带有前导的0。比如输入700&#xff0c;输出应该是7。 输入格式&#xff1a; 每个测试是一个3位的正整数。 输出格式&a…

抛弃优启Grub4dos和PE大多数时间可以这样用

抛弃优启Grub4dos和PE大多数时间可以这样用 在能够进入Windows的情况下&#xff0c;Grub4dos和PE大多数时间可以这样用 http://yunpan.cn/cyuuUtUQMfmGN 提取码 c2acGrub4dos的出现颠覆了传统的EZBOOT光盘启动模式&#xff0c;很多人用grub4dos来实现优盘启动&#xff0c;同时g…

Java最佳实践–队列之战和链接的ConcurrentHashMap

在使用Java编程语言时&#xff0c;我们将继续讨论与建议的实践有关的系列文章&#xff0c;我们将在四个具有相关语义的流行Queue实现类之间进行性能比较。 为了使事情变得更现实&#xff0c;我们将在多线程环境下进行测试&#xff0c;以讨论和演示如何将ArrayBlockingQueue &am…

HDU 5652 India and China Origins(二分 + BFS)

本文链接:http://www.cnblogs.com/Ash-ly/p/5398867.html 题意&#xff1a; 中国和印度之间有一片地方&#xff0c;把这片地方抽象化&#xff0c;于是就可以看成一个N * M矩阵&#xff0c;其中黑色的代表高山不能走过去&#xff0c;白色的代表平原&#xff0c;可以通行,人每次可…

C语言%.2f四舍五入

#include <stdio.h> int main() {double d 1.199;printf("%.2f", d);return 0; }输出1.20 如果不想让其四舍五入可以这样&#xff1a; #include <stdio.h> #include <math.h> int main() {double d 1.199;printf("%.2f", floor(d * 1…

关于使用racthet的push.js

racthet的push是用来跳转另外一个页面的效果的。但是必须在服务器的环境下支持。如果想要让本地html访问支持的话需要添加 转载于:https://www.cnblogs.com/djawh/p/4623925.html