//1 新建对象

var box = new Object();
box.name = "lee";
box.age = 100;
box.run = function(){
return this.name+this.age+"运行中";
}
alert(box.run()); //lee100运行中
//缺点:不能重复,如果再新建一个对象还要写大量重复代码 //2 工厂模式
function box(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name+this.age+"运行中";
};
return obj; //返回对象
}
var box1 = box("lee",100);
var box2 = box("dang",200);
alert(box1.run());
alert(box2.run());
//缺点:无法搞清实例是哪个对象的实例
alert(typeof box1); //object
alert(box1 instanceof Object);//true,无法识别是哪个对象的实例
alert(box1 instanceof box); //false,box是function
alert(typeof box); //function //3 构造函数创建对象:解决上述问题,不知道是哪个对象的实例
function Box(name,age){ //构造函数名首字母大写(非强制,为了区分),不用返回对象
this.name = name;
this.age = age;
this.run = function(){
return this.name+this.age+"运行中";
};
}
var box1 = new Box("lee",100); //构造函数必须通过new来调用
var box2 = new Box("lee",100);
alert(box1.run());
alert(typeof box1);//object
alert(box1 instanceof Box); //true,证明是Box的实例
//缺点:引用地址的不一致
alert(box1.name == box2.name); //true
alert(box1.run() == box2.run()); //true 方法的值一样,因为传参一直
alert(box1.run == box2.run); //false 方法其实是一种引用地址,
//解决办法:使用了全局的函数run()来解决了保证引用地址一致,单没什么必要,了解就行
// 可以使用原型
function Box(name, age) {
this.name = name;
this.age = age;
this.run = run;
}
function run() { //通过外面调用,保证引用地址一致
return this.name + this.age + '运行中...';
} //原型
//4 构造函数创建原型
//我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。逻辑上可以这么理解:prototype通过调用构造函数而创建的那个对象的原型对象。使用原型的好处可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。
function Box(){}
Box.prototype.name = "lee";
Box.prototype.age = 100;
Box.prototype.run = function(){
return this.name + this.age + '运行中...';
}
var box1 = new Box();
var box2 = new Box();
alert(box1.run == box2.run); //true,方法的引用地址保持一致 alert(Box.prototype.isPrototypeOf(box1));//true,判断一个对象是否指向了该构造函数的原型对象,可以使用isPrototypeOf()方法来测试。 //在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。__proto__属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性constructor。通过这两个属性,就可以访问到原型里的属性和方法了。
alert(box1.__proto__); //object,但IE浏览器在脚本访问__proto__会不能识别
alert(box1.constructor); //构造函数的函数体返回 /*
原型模式的执行流程:就近原则
1.先查找构造函数实例里的属性或方法,如果有,立刻返回;
2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;*/
var box = new Box();
alert(box.name); //lee
box.name = "jack";
alert(box.name); //jack
delete box.name;
alert(box.name); //lee,可以删除构造函数里的属性 //如何判断属性是在构造函数的实例里,还是在原型里?可以使用hasOwnProperty()函数来验证
alert(box.hasOwnProperty("name")); //实例里有true,没有后返回false
//in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。
alert("name" in box); //5 为了让属性和方法更好的体现封装的效果,减少不必要的输入,原型的创建可以使用字面量方式
function Box(){};
Box.prototype={
name:"lee",
age:100,
run:function(){
return this.name + this.age + '运行中...';
}
} //使用构造函数创建原型对象和使用字面量创建对象在使用上基本相同,但还是有一些区别,字面量创建的方式使用constructor属性不会指向实例,而会指向Object,构造函数创建的方式则相反。
alert(box.constructor == Box); //字面量方式,返回false,否则,true
alert(box.constructor == Object); //字面量方式,返回true,否则,false
//如果想让字面量方式的constructor指向实例对象,那么可以这么做:
Box.prototype = {
constructor : Box, //直接强制指向即可
};
//PS:字面量方式为什么constructor会指向Object?因为Box.prototype={};这种写法其实就是创建了一个新对象。而每创建一个函数,就会同时创建它prototype,这个对象也会自动获取constructor属性。所以,新对象的constructor重写了Box原来的constructor,因此会指向新对象,那个新对象没有指定构造函数,那么就默认为Object。 //原型的声明是有先后顺序的,所以,重写的原型会切断之前的原型。
function Box() {}; Box.prototype = { //原型被重写了
constructor : Box,
name : 'Lee',
age : 100,
run : function () {
return this.name + this.age + '运行中...';
}
};
Box.prototype = {
age = 200
};
var box = new Box(); //在这里声明
alert(box.run()); //box只是最初声明的原型 //原型对象不仅仅可以在自定义对象的情况下使用,而ECMAScript内置的引用类型都可以使用这种方式,并且内置的引用类型本身也使用了原型。
alert(Array.prototype.sort); //sort就是Array类型的原型方法
alert(String.prototype.substring); //substring就是String类型的原型方法 String.prototype.addstring = function () { //给String类型添加一个方法
return this + ',被添加了!'; //this代表调用的字符串
}; alert('Lee'.addstring()); //使用这个方法
////PS:尽管给原生的内置引用类型添加方法使用起来特别方便,但我们不推荐使用这种方法。因为它可能会导致命名冲突,不利于代码维护。 //原型的缺点:不能传参和共享(共享也是原型的最大优点) //原型中所有属性是被很多实例共享的,共享对于函数非常合适,对于包含基本值的属性也还可以。但如果属性包含引用类型,就存在一定的问题:
function Box() {};
Box.prototype = {
constructor : Box,
name : 'Lee',
age : 100,
family : ['父亲', '母亲', '妹妹'], //添加了一个数组属性
run : function () {
return this.name + this.age + this.family;
}
}; var box1 = new Box();
box1.family.push('哥哥'); //在实例中添加'哥哥'
alert(box1.run()); var box2 = new Box();
alert(box2.run()); //共享带来的麻烦,也有'哥哥'了 //6 构造函数+原型模式 为了解决传参和共享的问题
function Box(name,age){
this.name = name;
this.age = age;
this.family = ["baba","mama","meimei"];
};
Box.prototype={
constructor:Box,
run:function(){
return this.name+this.age+this.family;
}
};
var box1 = new Box();
box1.family.push("gege");
alert(box1.family);
var box2 = new Box();
alert(box2.family);
这种方法解决了传参和引用共享的大难题,是比较好的方法 //7 动态原型模式,相比上边的方法封装性好一点,要注意一点,不可以再使用字面量的方式重写原型,因为会切断实例和新原型之间的联系。
function Box(name,age){
this.name = name;
this.age = age;
this.family = ["baba","mama","meimei"];
if(typeof this.run != "function"){
Box.prototype.run = function(){
return this.name+this.age+"运行中";
};
}
} var box1 = new Box();
box1.family.push("gege");
alert(box1.family);
var box2 = new Box();
alert(box2.family); //8 如果上述都不能满足条件,可以使用寄生构造函数
//其实就是工厂模式+构造函数模式,比较通用,但不能确定对象关系,所以,在可以使用之前所说的模式时,不建议使用此模式。
function Box(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name+this.age+"运行中";
}
return obj;
}
//在什么情况下使用寄生构造函数比较合适呢?假设要创建一个具有额外方法的引用类型。由于之前说明不建议直接String.prototype.addstring,可以通过寄生构造的方式添加。
function myString(string){
var str = new String(string);
str.addstring = function(){
return this+',被添加了!';
};
return str;
}
var box = new myString("lee");
alert(box.addstring());
//在一些安全的环境中,比如禁止使用this和new,这里的this是构造函数里不使用this,这里的new是在外部实例化构造函数时不使用new。这种创建方式叫做稳妥构造函数。
function Box(name,age){
var obj = new Object();
obj.run = function(){
return name+age+"运行中";
};
return obj;
}
var box = Box("lee",100); //不使用new
alert(box.run());
//稳妥构造函数和寄生相似

js对象的创建与原型总结的更多相关文章

  1. js对象的创建

    一.通过对象直接量来创建 var emptyt={};  //相当于var empty=new Object; //如果属性名中包含空格.连字符(-).还有关键字,保留字时,要用字符串表示 var b ...

  2. js 对象的创建方式和对象的区别

    js一个有三种方法创建对象,这里做一个总结. 1.对象直接量 所谓对象直接量,可以看做是一副映射表,这个方法也是最直接的一个方法,个人比较建议, 1 2 3 4 5 6 7 8 9 10 11 12 ...

  3. js对象的创建模式

    方式一: Object构造函数模式 * 套路: 先创建空Object对象, 再动态添加属性/方法 * 适用场景: 起始时不确定对象内部数据 * 问题: 语句太多 /* 一个人: name:" ...

  4. JS 对象API之获取原型对象

    1.从 构造函数 获得 原型对象: 构造函数.prototype 2.从 对象实例 获得 父级原型对象: 方法一: 对象实例.__proto__        [ 有兼容性问题,不建议使用] 方法二: ...

  5. JS对象中,在原型链上找到属性后 最终将值拷贝给原对象 而不是引用

    遇到一个面试题 要求写一个函数A,每次进行new操作时候能输出2,3,4,5... new A() // 输出2 new A() // 输出3 new A() // 输出4 function A() ...

  6. JS对象的创建与使用

    本文内容:     1.介绍对象的两种类型:     2.创建对象并添加成员:     3.访问对象属性:     4.利用for循环枚举对象的属性类型:     5.利用关键字delete删除对象成 ...

  7. js对象的几种创建方式和js实现继承的方式[转]

    一.js对象的创建方式 1. 使用Object构造函数来创建一个对象,下面代码创建了一个person对象,并用两种方式打印出了Name的属性值. var person = new Object(); ...

  8. javascript基础-js对象

    一.js对象的创建 1.普通最简单的方式 var teacher = new Object( ); teacher.name = "zhangsan"; teacher.age = ...

  9. 探讨一下js中的继承和原型链

    ---恢复内容开始--- 每个JS对象一定对应一个原型对象,并从原型对象继承属性和方法. 也就是说 对象的__proto__属性的值就是它所对应的原型对象, 而prototype 只有函数才有的属性. ...

随机推荐

  1. pro*c调用过程

    数据库内有无参数过程名为procedure. pro*c调用过程 EXEC SQL EXECUTE   BEGIN     procedure;   END; END-EXEC; 需要在cfg配置文件 ...

  2. Python中sorted()方法

    Python中sorted()方法的用法 1.先说一下iterable,中文意思是迭代器. Python的帮助文档中对iterable的解释是:iteralbe指的是能够一次返回它的一个成员的对象.i ...

  3. 2.3---删除链表的结点,不提供头结点(CC150)

    这里,注意如果是尾结点,那么无解. public class Solution { public void deleteNode(ListNode node) { //利用李代桃僵 // // if( ...

  4. python suds 一坑

    当被调用服务的返回xml内容值不是按照wsdl文件描述定义的, 就莫名奇妙返回suds.WebFault 没有更多详细信息! 于是将源码解压,并插入到sys.path[0], 通过设置断点的方式找出非 ...

  5. 插入备份数据 报 IDENTITY_INSERT 为 ON 时解决方法

    SQL Server 2008 R2 x64 下 事情是这样的, 使用Navcate的数据导出备份工具导出表的记录 INSERT INTO [xxx_users] VALUES (1, 'tom ', ...

  6. discuz论坛移植修改数据库配置

    从其他地方拷贝的discuz源码,可能需要修改数据库配置 分别打开discuz目录下面以下三个文件 discuzRoot/uc_server/data/config.inc.phpdiscuzRoot ...

  7. 循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate)的区别

    表示“重复”这个含义的词有很多, 比如循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称 ...

  8. devstack meaning of: n-cond, n-novnc and n-xvnc

    devstack has shortened names for a number of services, e.g. g-api = glance api g-reg = glance regist ...

  9. 在eclipse上开发hadoop2.5.2程序的快捷方法

    本文仍然使用MapReduce的经典例子 WordCount来测试eclipse的开发环境. 与大部分教程不同的是,本文使用的hadoop是2.5.2的版本,相较于之前的0.X版本,hadoop 2. ...

  10. c++面试题目解析

    1.指针和引用的区别 答:A.指针可修改,引用不可改. B.指针占用内存,引用不占内存. C.引用不能为空   指针可以为空. 2.memcpy和strcpy的区别 答:strcpy  会拷贝到\0结 ...