工厂模式

该模值抽象了创建具体对象de过程。用函数来封装噫特定接口创建对象的细节。

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("Chiaki",21,"Software Engineer");
person2=createPerson("Wu",20,"Student");

特点:可以无数次调用,解决了创建多个相似对象的问题,但没有解决对象识别的问题(即怎样知道一个对象的类型)。

构造函数模式

创建自定义的构造函数,从而定义自定义对象类型的属性方法。

function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
alert(this.name);
};
}
var person1=new Person("Chiaki",21,"Software Engineer");//person1的constructor(构造函数)属性指向Person
var person2=new Person("Wu",20,"Student");//person2的constructor(构造函数)属性指向Person

person1和person2都有一个constructor(构造函数)属性,该属性指向person.

alert(person1.constructor==Person);//true
alert(person2.constructor==Person);//true

构造函数模式与工厂模式的区别:

1、没有显示的创建对象;

2、直接将属性和方法赋给this对象;

3、没有return语句;

4、构造函数函数名以大写字母开头,非构造函数函数名以小写字母开头;

5、创建构造函数的新实例必须使用new操作符,例如var person1=new Person(“Chiaki”,21,”Web Engineer”);

6、将来可以将他的实例标识为一种特定的类型。

构造函数与其他函数的区别与联系:两者的调用方式不同;任何函数只要用new操作符调用,就可以把它当作构造函数,不通过new操作符调用,则和普通函数没什么区别。

//将上例当作构造函数使用
var person=new Person("Chiaki",21,"Software Engineer");
person.sayName();//Chiaki
//作为普通函数调用
Person("Wu",20,"Student");
window.sayName();//Wu//在全局作用域中调用一个函数,this对象总是指向Global对象(即浏览器的window对象)
//在另一个对象作用域中调用
var o=new Object();
Person.call(o,"lola",21,"designer");//使用call()在对象o的作用域中调用Person()函数,调用后o就拥有了Person()函数的所有属性和sayName()方法
o.sayName();//lola

缺点:每个方法都要在每个实例上重新创建一遍。

alert(person1.sayName==person2.sayName);//false

解决方法:把函数定义转到构造函数外,但是此方法可能需要定义多个全局函数,将导致该自定义引用类型毫无封装性可言。

function Person(name,ago,job){
this.name=name;
this.age=age;
this.job;
this.sayName=sayName;
}
function sayName(){
alert(this.name);
}
var person1=new Person("Chiaki",21,"Software Engineer");
var person2=new Person("Wu",20,"Student");
//person1和person2对象共享在全局作用域中定义的同一个sayName函数

原型模式

我们创建的每一个函数都有一个property(原型)属性,这个属性是一个指针,指向一个对象(该对象包含可以由特定类型的所有实例共享的属性和方法)。

function Person(){
}
Person.prototype.name="Chiaki";
Person.prototype.age=21;
Person.prototype.job="Software Engineer";
Person.prototype.sayName=function(){
alert(this.name);
};
var person1=new Person();
person1.sayName();//Chiaki
var person2=new Person();
person2.sayName();//Chiaki

这里写图片描述

创建一个新函数就会根据特定的规则为其生成一个prototype属性,该属性指向函数的原型对象,原型对象自动获得一个constructor属性,这个属性包含一个指向prototype属性所在函数的指针。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性[[Prototype]]),指向构造函数的原型对象。

可以通过对象实例访问保存在原型中的值,却不能通过对象实例重写原型中的值(当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性)。

function Person(){
}
Person.prototype.name="Chiaki";
Person.prototype.age=21;
Person.prototype.job="Software Engineer";
Person.prototype.sayName=function(){
alert(this.name);
};
var person1=new Person();
var person2=new Person();
person1.name="Wu";
alert(person1.name);//Wu——来自实例//当alert()访问person1.name时,在该实例上搜索到一个名为name的属性,则不必搜索原型
alert(person2.name);//Chiaki——来自原型//当alert()访问person2.name时,在该实例上搜索不到一个名为name的属性,就继续搜索原型,结果在那里找到了name属性。

使用delete操作符可以完全删除实例属性:。

var person1=new Person();
var person2=new Person();
person1.name="Wu";
alert(person1.name);//Wu
alert(person2.name);//Chiaki
delete person1.name;
alert(person1.name);//Chiaki//delete操作符删除了person1.name,从而恢复了对原型中name属性的连接

可使用hasOwnProperty()方法检测一个属性是否存在于实例中,还是存在原型中。

alert(person1.hasOwnProperty("name"));//false//person1实例中没有name属性
person1.name="Wu";//person1重写name属性,即person1实例中有name属性
alert(person1.hasOwnProperty("name"));//true//原型与in操作符:单独使用、在for-in循环中使用。

单独使用时,in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在实例中还是原型中。

alert("属性" in 实例);如果该实例中有该属性则返回true,否则返回false。

function Person(){
}
Person.prototype.name="Chiaki";
Person.prototype.age=21;
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//name属性在原型中
alert("name" in person1);//true
person1.name="Wu";alert(person1.hasOwnProperty("name"));//true//重新name属性后,person1实例中有name属性
alert("name" in person1);//true
hasPrototypeProperty() 方法判断访问到的属性是否存在于原型中。
var person =new Person();
alert(hasPrototypeProperty(perso,"name"));//true
person.name="Wu";//重写person.name,原型中的name属性被屏蔽,则访问到的name属性来自实例person
alert(hasPrototypeProperty(person,"name");//false

in操作符和hasOwnProperty()方法同时使用可以判断属性是处于对象中还是处于原型中。

在for-in循环中使用,返回所有能够通过对象访问的可枚举(enumerated)属性,包括实例中的属性和原型中的属性。屏蔽了原型中不可枚举属性(即[[enumerable]]设置为false)的实例属性也会在for-in循环中返回(IE 8 及更早的版本除外).

var o={
name:"Chiaki"
};
for (var prop in o){
alert(prop);//name
}

IE早期版有个bug会导致屏蔽不可枚举属性的实例属性不会出现在for-in循环中。

默认不可枚举的属性和方法有:hasOwnProperty()、propertyIsEnumerable()、toLocaleString(),toString()和valueOf();ECMAScript5也将constructor和prototype属性的[[Enumerable]]设置为false。

Object.keys()方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。

var keys=Object.keys(Person.prototype);
alert(keys);//"name,age,job,sayName"
var p1=new Person();
p1.name="Wu";
p1.age=20;
var p1Keys=Object,keys(p1);
alert(p1Keys);//"name,age"
Object.getOwnPropertyNames()返回所有实例属性
var keys=Object.getOwnPropertyNames(Person.prototype);
alert(keys);//“constructor,name,age,job,sayName"

更简单的原型语法:

Person.prototype={}
function Person(){}
Person.prototype={
name:"Chiaki",
age:21,
job:"Software Engineer",
sayName:function(){
alert(this.name);
}
};

上例中,我们将Person.prototype设置为等于一个以对象字面量形式创建的新对象,此时constructor属性不再指向Person.(原因:Person.prototype={}本质上完全重写了创建构造函数Person时默认的prototype对象,因此constructor属性就变成了新对象的constructor属性【指向Object构造函数】)。

此时如果constructor的值很重要时可特意将它设置回适当的值,如下:

funtion Person(){
}
Person.prototype={
constructor:Person,//重设constructor属性将导致它的[[enumerable]]特性被设置为true,可以通过Object.defineProperty()修改成不可枚举的
name:"Chiaki",
age:21,
job:"Software Engineer",
sayName:function(){
alert(this.name);
}
};

原型的动态性:由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能够立即从实例上反应出——即使先创建了实例后修改原型也照样如此。

var friend=new Person();
Person.prototype.sayHi=function(){
alert("hi");
}
friend.sayHi();//"hi"

实例和原型时间的连接是一个指针而非一个副本,因此可以随时为原型添加属性和方法,并且修改能够立即在所有对象实例中反应出来。但是如果是重写整个原型对象,将会切断构造函数和最初原型之间的联系。实例中的指针仅指向原型而非构造函数。

原型对象的问题:1、省略了为构造函数传递初始化参数的环节,结果所有实例在默认情况下都将取得相同的属性值;2、原型对象具有共享的本性,对于包含引用类型值的属性,如果一个原型对象创建的两个实例其中一个修改了引用类型的属性值,将导致另一个实例的该引用类型的属性值也被改变。

function Person(){}
Person.prototype={
constructor=Person,
friends:["lola","cherry"],
}
var person1=new Person();
var person2=new Person();
person1.friends.push("van");
alert(person1.friends);//lala,cherry,van
alert(person2.friends);//lola,cherry,van
alert(person1.friends==person2.friends)//true

组合使用构造函数模式和原型模式

构造函数模式用于定义实例属性,原型模式用于定义方法和共享属性。

function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.friends=["lola","cherry"];
}
Person.prototype={
constructor:Person,
sayName:function(){
alert(this.name);
}
}
var person1=new Person("Chiaki",21,"Software Engineer");
var person2=new Person("Wu",20,"Student");
person1.friends.push("Van");
alert(person1.friends);//lola,cherry,Van
alert(person2.friends);//lola,cherry
alert(person1.friends==person2.friends);//false//friends是构造函数中定义的实例属性
alert(person1.sayName==person2.sayName);//trues//sayName()是原型中定义的,具有共享性

动态原型模式

把所有信息封装在构造函数中,而通过在构造函数中初始化原型又保持了同时使用构造函数和原型的优点。即通过检查某个应该村咋的方法是否有效来决定是否需要初始化原型。

function Person(name,age,job){
//属性
this.name=name;
this.age=age;
this.job=job;
//方法初始化之后应该存在的任何属性的方法
if(typeof this.sayName!="function"){//检查
Person.prototype.sayName=function(){
alert(this.name);
}
}
}
var friend=new Person("Chiaki",21,"Software Engineer");
friend.sayName();

寄生式构造函数模式

创建一个函数以封装创建对象的代码,然后返回新创建的对象。

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("Chiaki",21,"Software Engineer");
friend.sayName();//Chiaki

构造函数在不返回值的情况下默认会返回新对象实例,而通过在构造函数的末尾添加一个return语句,可以重写调用构造函数时返回的值。构造函数返回的对象与构造函数或者构造函数的原型属性之间没有关系。

稳妥构造函数模式

稳妥对象:即没有公共属性,且方法也不用this的对象。适用于安全的环境中(该环境下禁用this和new)或者在在防止数据被其他应用程序改动时使用。

function Person(name,age,job){
//创建要返回的对象
var o=new Object();
//可以在这里定义私有变量和函数
//添加方法
o.sayName=function(){
alert(name);
}
//返回对象
return o;
}

这种模式下创建的对象在,除使用sayName方法外,没办法访问name值。

javascript面向对象学习笔记——创建对象(转)的更多相关文章

  1. JavaScript面向对象学习笔记

    JavaScript 常被描述为一种基于原型的语言 (prototype-based language)--每个对象拥有一个原型对象,对象以其原型为模板.从原型继承方法和属性.原型对象也可能拥有原型, ...

  2. JavaScript正则表达式学习笔记(二) - 打怪升级

    本文接上篇,基础部分相对薄弱的同学请移步<JavaScript正则表达式学习笔记(一) - 理论基础>.上文介绍了8种JavaScript正则表达式的属性,本文还会追加介绍几种JavaSc ...

  3. javascript正则表达式 - 学习笔记

    JavaScript 正则表达式 学习笔记 标签(空格分隔): 基础 JavaScript 正则表达式是用于匹配字符串中字符组合的模式.在javascript中,正则表达式也是对象.这些模式被用于Re ...

  4. JavaScript简易学习笔记

    学习地址:http://www.w3school.com.cn/js/index.asp 文字版: https://github.com/songzhenhua/github/blob/master/ ...

  5. javaScript 对象学习笔记

    javaScript 对象学习笔记 关于对象,这对我们软件工程到学生来说是不陌生的. 因为这个内容是在过年学到,事儿多,断断续续,总感觉有一丝不顺畅,但总结还是要写一下的 JavaScript 对象 ...

  6. 【MarkMark学习笔记学习笔记】javascript/js 学习笔记

    1.0, 概述.JavaScript是ECMAScript的实现之一 2.0,在HTML中使用JavaScript. 2.1 3.0,基本概念 3.1,ECMAScript中的一切(变量,函数名,操作 ...

  7. Javascript MVC 学习笔记(一) 模型和数据

    写在前面 近期在看<MVC的Javascript富应用开发>一书.本来是抱着一口气读完的想法去看的.结果才看了一点就傻眼了:太多不懂的地方了. 仅仅好看一点查一点,一点一点往下看吧,进度虽 ...

  8. Javascript作用域学习笔记(三)

    看完<你不知道的javascript>上,对作用域的新的理解(2018-9-25更) 一.学习笔记:   1.javascript中的作用域和作用域链 +  每个函数在被调用时都会创建一个 ...

  9. PHP:面向对象学习笔记,重点模拟Mixin(掺入)

    背景 相对于Python.Node和Ruby来说PHP算是一门容易学习和使用的语言,因为这个特点也使其成为WEB开发领域的佼佼者,本文记录一下我对PHP面向对象部分的学习笔记. 先来一个复杂的例子:M ...

随机推荐

  1. SQL注入中利用XP_cmdshell提权的用法(转)

    先来介绍一下子服务器的基本情况,windows 2000 adv server 中文版,据称 打过了sp3,asp+iis+mssql .首先扫描了一下子端口,呵呵,开始的一般步骤. 端口21开放: ...

  2. SDUT 3568 Rock Paper Scissors 状压统计

    就是改成把一个字符串改成三进制状压,然后分成前5位,后5位统计, 然后直接统计 f[i][j][k]代表,后5局状压为k的,前5局比和j状态比输了5局的有多少个人 复杂度是O(T*30000*25*m ...

  3. 用javascript 面向对象制作坦克大战(四)

    我们现在还差一个重要的功能,没错,敌人坦克的创建以及子弹击中敌人坦克时的碰撞检测功能. 5.  创建敌人坦克完成炮弹碰撞检测 5.1   创建敌人坦克对象 敌人坦克和玩家坦克一样,同样继承自我们的坦克 ...

  4. 如何从ST网站找到对应的固件库

    ST官方网站改版后,基本上很难搜索到固件库的地址,找了半天才找到固件库的下载地址,通过此方法可以找到其他需要的资源,故记下来方便大家. 下载的网站地址为: Home>Tools and Soft ...

  5. 关于java异常的一点思考

    关于异常的一点思考 异常生命周期 异常的来源 所有的异常都是抛出来的 有底层api抛出的 有自定义抛出的 异常的处理 1, 运行时异常 不做任何处理仍可编译通过 不建议捕获(不建议用异常来做流程控制, ...

  6. <Araxis Merge>Windows平台下的Merge概览

    它是什么 Merge是一个来自Araxis的可视化文件比较/合并及文件夹同步的应用程序. 用户界面使用英语.德语.日语.法语.国际西班牙语.汉语(繁体和简体)进行本地化了. 优势 对于软件工程师和网站 ...

  7. Mac vim iterm2配色方案

    转自:http://www.vpsee.com/2013/09/use-the-solarized-color-theme-on-mac-os-x-terminal/ 相信长期浸泡在终端和代码的小伙伴 ...

  8. 转载:mac系统XAMPP配置虚拟主机

    安装完xampp后,想添加一个virsualhost,一直报错.查了半天资料,都是乱说,后来看到了一篇国外的文章,终于弄出来了,整理一下. 第一步,配置本地hosts sudo vi /etc/hos ...

  9. Codeforces 375

    A 7的所有的余数都可以用1,6,8,9排列得到,然后搞一下就可以了. B 可以用类似于单调队列的东西搞.具体看代码: /* * Problem: B. Maximum Submatrix 2 * A ...

  10. http和数据库sql分析与窃听技术

    用tunnel,tunnel是一种技术称谓,将其放到真正的服务器和客户端之间.调试阶段可以使用webcream运行tomcat作为模拟的真正的服务器. 具体:用apache axis及其项目中的工具t ...