工厂模式

该模值抽象了创建具体对象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. IOS UIActivityIndicatorView 等待指示器

    自己做的一个 等待指示器 #import <UIKit/UIKit.h> @interface RockIndicatorView : UIView { } @property(nonat ...

  2. BFC--绝对值得你思考

    CSS BFC(Block Formatting Context)      BFC是W3C CSS 2.1规范中的一个概念,他决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用.     ...

  3. C字符串和C++中string的区别 &amp;&amp;&amp;&amp;C++中int型与string型互相转换

    在C++中则把字符串封装成了一种数据类型string,可以直接声明变量并进行赋值等字符串操作.以下是C字符串和C++中string的区别:   C字符串 string对象(C++) 所需的头文件名称 ...

  4. HDU-3864 D_num Miller_Rabin和Pollard_rho

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3864 题意:给定一个数n,求n的因子只有四个的情况. Miller_Rabin和Pollard_rho ...

  5. 应用数据存储到sdcard上一定要规范,android4.4.2有新规范

    如果你的android设备有内部存储空间,即通常所说的机身存储(这就是指主要外部存储),那么你从外部插入SD卡就是一个二级外部存储设备. 最新的Android 4.4系统中,外置存储卡(SD卡)被称为 ...

  6. j2ee的十三个规范

    转载 今天在做连接oracle数据库的时候,感受到了什么是规范.平时听到别人说学习j2ee一定要学习他的十三个规范,大概的知道每个规范是做什么的,每个“接口”是做什么的.          很早就听过 ...

  7. 转】Nginx+tomcat配置集群负载均衡

    原博文出自于:http://blog.csdn.net/bruce_6/article/details/38228299         感谢! 相信很多人都听过nginx,这个小巧的东西慢慢地在吞食 ...

  8. YII开发技巧分享——模型(models)中rules自定义验证规则

    YII的models中的rules部分是一些表单的验证规则,对于表单验证十分有用,在相应的视图(views)里面添加了表单,在表单被提交之前程序都会自动先来这里面的规则里验证,只有通过对其有效的限制规 ...

  9. JavaIO(01)File类详解

    File类 file类中的主要方法和变量   常量: 表示路径的分割符:(windows) 作用:根据java可移植性的特点,编写路径一定要符合本地操作系统要求的分割符: public static ...

  10. [iOS基础控件 - 6.11.3] 私人通讯录Demo 控制器的数据传递、存储

    A.需求 1.搭建一个"私人通讯录"Demo 2.模拟登陆界面 账号 密码 记住密码开关 自动登陆开关 登陆按钮 3.退出注销 4.增删改查 5.恢复数据(取消修改)   这个代码 ...