JavaScript原型模式-理解对象
一:简述
当初学编程一看到什么什么模式就比较头晕,不过本文我们通过简单的示例代码来说一下js 对象这个话题 ,来看下如何理解这个原型模式。
二:理解对象
1.简单对象
js对象中没有java、C#等类的概念。但是在js中 一切皆对象嘛 我们可以这么写一个实例
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body> <script>
//创建一个对象
var person = new Object();
//声明属性
person.name = 'hello';
person.age = 29;
person.job = 'Software Engineer';
//声明方法
person.sayName = function () {
alert(this.name);
}
</script>
</body>
</html>
是不是很像一个class。但这是早期js创建对象的写法,后来出现了对象字面量的写法 简化了上面的写法
2.对象字面量
我们来改进上面的写法
var person = {
//属性
name: 'hello',
age: 29,
job: 'Software Engineer',
//声明方法
sayName: function () {
alert(this.name);
}
}
是不是简化了很多,但是上面两种创建的对象如果创建多了会产生大量重复代码 ,所以也就出现了以下第三种模式(又是模式....)
3.工厂模式
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body> <script>
//用函数来包装
function createPerson() {
var person = new Object();
//声明属性
person.name = 'hello';
person.age = 29;
person.job = 'Software Engineer';
//声明方法
person.sayName = function () {
alert(this.name);
}
return person;
}
//调用
var person1 = createPerson('tom', 21, 'baidu');
var person2 = createPerson('tony', 31, 'tencent');
</script>
</body>
</html>
工厂就是把东西加工、包装成一个对象。 其实我们大多数的写法也就是这么个模式 。但是这样我们怎么知道这个对象的类型呢 ?随着js发展又出来一个新模式
4.构造函数模式
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body> <script> function Person(name,age,job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
alert(this.name);
}
} var pserson1 = new Person('tom', 21, 'baidu');
var pserson2= new Person('tony', 31, 'tencent');
</script>
</body>
</html>
看着是不是跟对象字面量很像。这个模式跟工厂模式对比来看
a.没有显示的创建对象
b.直接将属性和方法赋值给了this对象
c.没有return
d.执行构造函数中的代码(在Person新对象中添加属性和方法)
console.info(person1.constructor == Person);//true
console.info(person1.constructor == Person);//true
对象的constructor属性 是用来标识对象类型的 ,可以将他的实例标识为一种特定的类型
说说这个特殊的函数--构造函数 ,它跟函数的唯一区别就是调用的方式不同(有啥不同啊。。)
只要是能通过new操作符来调用的函数就可以作为构造函数。(没new的就是普通函数呗O(∩_∩)O)
//我是构造函数
var pserson1 = new Person('tom', 21, 'baidu');
//我是普通函数
person('tony', 31, 'tencent');
构造函数模式也有自己的问题。每个方法都要在每个实例上重新创建一遍。
构造函数的另一种定义:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script>
function Person(name,age,job) {
this.name = name;
this.age = age;
this.job = job;
//第一种写法
this.sayName = function () {
alert(this.name);
}
//第二种写法
this.sayName = new Function("alert(this.name)")
} </script>
</body>
</html>
这样就可以看出person1.sayName 不等于person2.sayName了 因为不同实例的同名函数是不相等的
但是我们可以这么写:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script>
function Person(name,age,job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName
}
function sayName() {
alert(this.name);
}
</script>
</body>
</html>
但是这样虽然是函数指向相同了 但是方法多了 就没有封装性可言了 。
5.原型模式
我们每个函数都有一个prototype(原型)属性。它是构造函数中(就是new的函数)自动创建的对象实例的原型对象 (就是一new就有了)
好处:可以让所有对象实例共享它包含的属性和方法(可以直接添)如下
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script>
//声明一个空函数(首字母大写)
function Person() { }
//添加属性和方法
Person.prototype.name = "tony";
Person.prototype.age=29;
Person.prototype.job = 'baidu';
Person.prototype.sayName = function () {
alert(this.name);
} var person1 = new Person();
person1.sayName();//baidu var person2 = new Person();
person2.sayName();//baidu alert(person1.sayName == person2.sayName);//true
</script>
</body>
</html>
因为新对象的属性和方法都是共享的,所以person1和person2都是访问的同一个sayName函数
a.理解原型对象:
上面说到只要创建一个函数就会自动创建一个prototype属性,这个属性指向的就是函数的原型对象
Person.prototype.constructor就是Person
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script>
//声明一个函数(首字母大写)
function Person() { }
Person.prototype.name = "tony";
Person.prototype.age=29;
Person.prototype.job = 'baidu';
Person.prototype.sayName = function () {
alert(this.name);
}
var person1 = new Person();
console.info(person1);
</script>
</body>
</html>
chrome中打印输出结构:
虽然person1不包含任何属性和方法 ,但是我们可以使用person1.sayName() 这就是通过查找对象属性来实现的
person1就是实例 Person就是原型 当实例中的属性修改后
person1.name='1234' 不影响实例的属性 person2没修改 name还是tony
delete person1.name;
这个可以删除person1的实例属性 从而访问到原型中的值
(1)我们可以通过hasOwnProperty方法来判断本身是否有这个属性(就是判断自己有没有该属性 返回true、false)
<script>
//声明一个函数(首字母大写)
function Person() { }
Person.prototype.name = "tony";
Person.prototype.age=29;
Person.prototype.job = 'baidu';
Person.prototype.sayName = function () {
alert(this.name);
}
var person1 = new Person();
alert(person1.hasOwnProperty('name'));//false
person1.name = '123';//我自己重新赋值 有了该属性
alert(person1.hasOwnProperty('name'));//true
console.info(person1);
</script>
(2)通过 in操作符来判断(单独使用和在for循环中)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script>
//声明一个函数(首字母大写)
function Person() { }
Person.prototype.name = "tony";
Person.prototype.age=29;
Person.prototype.job = 'baidu';
Person.prototype.sayName = function () {
alert(this.name);
}
var person1 = new Person();
alert(person1.hasOwnProperty('name'));//false
alert('name' in person1) //true
person1.name = '123';//我自己重新赋值 有了该属性
alert(person1.hasOwnProperty('name'));//true
alert('name' in person1) //true </script>
</body>
</html>
可以看到in可以访问到原型中去查找也就返回了都是true 而hasOwnProperty只在本身查找
(3)我只想看是否在原型中的属性 使用hasPrototypeProperty (在原型中不在实例中的属性)
(4)像in的用法在ie等浏览器中是有bug的 所以es5提供了 Object.keys() 方法来获取所有枚举属性
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script>
//声明一个函数(首字母大写)
function Person() { }
Person.prototype.name = "tony";
Person.prototype.age=29;
Person.prototype.job = 'baidu';
Person.prototype.sayName = function () {
alert(this.name);
} var keys = Object.keys(Person.prototype);
alert(keys);//name,age,job,sayName
var person1 = new Person();
person1.name = '123';//我自己重新赋值 有了该属性
var keys2 = Object.keys(person1.prototype);
alert(keys2);//name </script>
</body>
</html>
上面原型写法完全可以用对象字面量的形势简写(注意字面量写法中的红字)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script>
//声明一个函数(首字母大写)
function Person() { }
Person.prototype = {
constructor:Person,//修正构造函数重新指向自己
name: "tony",
age: 29,
job: 'baidu',
sayName: function () {
alert(this.name);
}
}
//Person.prototype.name = "tony";
//Person.prototype.age=29;
//Person.prototype.job = 'baidu';
//Person.prototype.sayName = function () {
// alert(this.name);
//}
</script>
</body>
</html>
原型模式最大的问题是共享的本性导致的 。里面包含引用类型比如数组 也会跟着共享
所以原型模式一般不会单独出现
6.组合使用构造函数模式和原型模式
构造函数模式用来定义实例属性
原型模式用来定义方法和共享的属性
这种混合模式是目前es中使用最广泛和认同度最高的一种自定义类型的方法 这也是引用类型的一种默认方式
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script>
//声明一个函数(首字母大写)
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ["lili","tonk"];
}
Person.prototype = {
constructor: Person,
sayName: function () {
alert(this.name);
}
} var person1 = createPerson('tom', 21, 'baidu');
var person2 = createPerson('tony', 31, 'tencent'); person1.friends.push('van');
console.info(person1.friends);//lili、tonk、van
console.info(person2.friends);//lili、tonk
console.info(person1.friends == person2.friends);//false
console.info(person1.sayName == person2.sayName);//true
</script>
</body>
</html>
JavaScript原型模式-理解对象的更多相关文章
- javascript原型模式理解
传统的面向对象语言中,创建一个对象是通过使用类来创建一个对象的,比如通过类飞行器来创建一个对象,飞机. 而js这种没有类概念的动态设计语言中,创建对象是通过函数来创建的,所以通常也把js称为函数式语言 ...
- 面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统
面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统 原型模式和基于原型继承的JavaScript对象系统 在 Brendan Eich 为 JavaScrip ...
- Javascript原型模式总结梳理
在大多数面向对象语言中,对象总是由类中实例化而来,类和对象的关系就像模具跟模件一样.Javascript中没有类的概念,就算ES6中引入的class也不过是一种语法糖,本质上还是利用原型实现.在原型编 ...
- JavaScript原型模式
一.提到原型模式,和构造函数关系密切,先讲一下它 javascript没有类,通过函数来模拟实现类,用new来创建对象,函数内部的this指针来指向调用它的对象. 事例中创建对象myGril,这个对象 ...
- Javascript:原型模式类继承
原型模式 每个函数(准确说不是类.对象)都有一个prototype属性,这个属性是一个指针,指向一个对象. 使用原型对象的好处是可以让所有对象实例共享它包含的属性和方法. 1.原型对象 (1)当创 ...
- 通过JavaScript原型链理解基于原型的编程
零.此文动机 用了一段时间的Lua,用惯了Java C++等有Class关键字的语言,一直对Lua的中的面向对象技术感到费解,一个开源的objectlua更是看了n遍也没理解其中的原理,直到看到了Pr ...
- JavaScript原型模式(prototype)
1.原型是一个对象,其他对象可以通过它实现属性的继承所有对象在默认的情况下都有一个原型,因为原型的本身也是对象,所以一个类的真正原型是被类的内部[prototype]属性所指出.每个函数都有一个属性叫 ...
- JavaScript 面向对象编程 · 理解对象
前言: 在我们深入 面向对象编程之前 ,让我们先理解一下Javascript的 对象(Object),我们可以把ECMAScript对象想象成散列表,其值无非就是一组名值对,其中值可以是数据 ...
- 关于JavaScript 原型的理解
原型的含义是指:如果构造器有个原型对象A,则由该构造器创建的实例(Object Instance)都必然复制于A.““在JavaScript中,对象实例(Object Instance)并没有原型,而 ...
随机推荐
- [html] 学习笔记-Canvas使用路径
想要绘制其他图形,需要使用路径,使用路径包含4个步骤,开始创建路径.创建图形的路径.路径创建完成后关闭路径.设定绘制样式,之后就可以调用绘制方法绘制路径了. 1.绘制圆形 <!DOCTYPE h ...
- [html5]学习笔记一 新增的非主体结构元素
html新增加的非主体结构元素,主要是用来表示附加信息的,包括header,footer,hgroup,address元素. 1.header元素 header元素是一种具有引导和导航作用的结构元素, ...
- 第七届蓝桥杯javaB组真题解析-凑算式(第三题)
题目 /* 凑算式 B DEF A + --- + ------- = 10 C GHI (如果显示有问题,可以参见[图1.jpg]) 这个算式中A~I代表1~9的数字,不同的字母代表不同的数字. 比 ...
- java反射的理解与应用(某大神博客中看到的博文,写的真的太好了,果断转载作为笔记)
原文地址:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html#undefined 一.什么是反射机制 简单的来说,反射机制指的是程序 ...
- python之列表对象
1. 获取列表中的某个值 描述:获取下标所对应的值 语法: print(li[0]) #[取索引值] 样例: li = list(['a','b','c']) val=(li[0]) #获取下标所对应 ...
- Hadoop技巧(04):简易处理solr date 时区问题
阅读目录 序 创建collection 模拟程序 示例下载 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的, ...
- 做一个360度看车的效果玩玩(web)
前几天在 Lexus 官网看到有这样的一个效果:http://www.lexus.com.cn/models/es/360 于是顺手打开控制台看了下他们是怎么做的,发现使用的技术还是比较简单的,通过背 ...
- 一篇知乎的故事 - javascript技术贴
前言 就像文章题目所示,本文的发表源于知乎的一篇文章.文章链接如下:如果你想靠前端技术还房贷,你不能连这个都不会.这篇文章是群里水群时别人发的,像我这样的菜鸟角色才不会逛知乎~~~.这篇文章主要是讲了 ...
- [java多线程] - 锁机制&同步代码块&信号量
在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突.冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突.按照我的理解在java中实现同步的方式分为三种,分别是:同 ...
- c#模拟js escape方法(转)
实现URI字符串转化成escape格式的字符 public static string Escape(string s) { StringBuilder sb ...