博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS创建对象的7中方式
阅读量:5218 次
发布时间:2019-06-14

本文共 6692 字,大约阅读时间需要 22 分钟。

1、  工厂模式

2、  构造函数模式          [解决对象识别问题]

3、  原型模式                   [解决方法和属性共享问题]

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

5、  动态原型模式

6、  寄生构造函数模式

7、  稳妥构造函数模式

  • 最简单的方式:创建一个Object的实例,然后为它添加属性和方法。

缺点:使用同一个接口创建很多对象,会产生大量的重复代码

1 var person = new Object();2 person.name = 'mackxu';3 person.age = 23;4 person.job = 'Software Engineer';5 6 person.sayName = function() {7     debug(this.name);8 };
  • 工厂模式:这种模式抽象了创建具体对象的过程。

具体做法:用函数封装以特定接口创建对象的细节

缺点:对比上一个方法解决了创建多个相似对象的问题,但却没有解决对象识别的问题

1     function createPerson(name, age, job) { 2         var o = new Object(); 3         o.name = name; 4         o.age = age; 5         o.job = job; 6         o.sayName = function() { 7             debug(this.name); 8         }; 9         return o;10     }
  • 构造函数模式:解决了对象识别问题

使用new操作符调用构造函数经历4个步骤:

1、 创建一个新对象

2、 将构造函数的作用域赋给新对象(this指向这个新对象)

3、 执行构造函数中的代码(为这个新对象添加属性)

4、 返回新对象

1     function Emp(name, age, job) {2        this.name = name;3        this.age = age;4        this.job = job;5        this.sayName = function() {6            debug(this.name);7        };9     } var p = new Emp(); 模拟过程如下:
var p = {}; Emp.apply(p); p.__proto__ = Emp.prototype;

将构造函数当作函数

1 var person = new Person('mackxu', 23, 'Software Engineer'); 2     person.sayName(); 3     debug(person.constructor == Person); 4     debug(person instanceof Person);     5     //var person2 = Person('mack', 22, 'Doctor'); 6     //作为普通的函数 7     Person('mack', 22, 'Doctor'); 8     sayName();        // == window.sagName(); 9     //在另外一个对象的作用域中调用10     var o = new Object();11     //this 指向o对象12     Person.call(o, 'zhangsan', 23, 'Nurse');13     o.sayName();    //zhangsan    14     debug(o instanceof Person);        //false

问题:方法不能被实例共享

    解决方法有二:1、把方法定义到构造函数外面,但破坏了封装性

                2、用原型模式共享方法

  • 原型模式(解决属性方法共享问题)

每一个函数都有一个prototype属性,这个属性是一个对象,它的用途是保存可以由特定类型的所有实例共享的属性和方法。

1 function Person() { 2         //... 3     } 4     Person.prototype.name = 'mackxu'; 5     Person.prototype.age = 22; 6     Person.prototype.job = 'Software Engineer'; 7     Person.prototype.sayName = function() { 8         debug(this.name); 9     };10 debug(person.sayName == person2.sayName)    //true

理解原型:

1 debug(Person.prototype.isPrototypeOf(person));    //true 2 使用delete操作符删除实例的属性 3 使用hasOwnProperty()方法可以检测一个属性在实例中,还是在于原型中。 4 (准确的说:只能确定在实例中的属性,返回true) 5     debug(person2.hasOwnProperty('name'));    //false 6     debug('name' in person2);                //true 7     //自定义函数判断属性在原型中定义 8     function hasPrototypeProperty(object, name) { 9         return !object.hasOwnProperty(name) && (name in object);10     }11     debug(hasPrototypeProperty(person2, 'name'));    //true12     //会屏蔽原型中与实例中相同的属性13     for (var property in person) {14         debug(property);15     }

更简单的原型语法[字面量对象]

1 function Person() { 2         //... 3     } 4     Person.prototype = { 5         constructor: Person, 6         name : 'mackxu', 7         age  : 22, 8         job  : 'Software Engineer', 9         sayName: function() {10             debug(this.name);    11         }12     };13     var person2 = new Person();14     debug(person2.name);15     debug(person2 instanceof Person);        //true16     debug(person2.constructor);            //Person{}17     debug(Person.prototype.constructor);    //Person{}

原型的动态性

由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能够立即从实例上反映出来

——即使是先创建了实例后修改原型也照样如此。

1 function Person() { 2         //..... 3     } 4     var person = new Person(); 5     Person.prototype.sayHi = function() { 6          debug('Hi'); 7 }; 8  person.sayHi();        //Hi 9 10     Person.prototype = {11         name: 'mackxu',12         sayHi: function() {13             debug('Hi');14         }15     };16     person.sayHi();        //error

原理:

 

原生对象的原型

通过原生对象的原型,不仅可以取得所有默认方法的引用,而且可以定义新方法

    //为基本包装类型String添加自定义方法

String.prototype.startWith = function(text) {        return this.indexOf(text) == 0;    };    var msg = 'Hello World';    debug(msg.startWith('Hello'));    //true

原型对象的问题:

1、 省略了为构造函数传递初始化参数的环节,

2、 其共享本性导致的(对于引用类型属性)

function Person() {        //...    }    Person.prototype = {        constructor: Person,        students: ['aaa', 'bbb']    };    //students被实例所共享,违背了我们的初衷    var person2 = new Person();    debug(person2.students);    var person3 = new Person();    person2.students.push('ccc');         debug(person3.students);        //"aaa", "bbb", "ccc"

3、 实例:属性是自己的,方法是被共享的

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

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

结果,每个实例都有都会有自己的一份实例属性的副本,同时共享着对方的方法引用

1     function Person(name, age, job) { 2         this.name = name; 3         this.age = age; 4         this.job = job; 5         this.friends = ['zhangsan', 'lisi']; 6     } 7     Person.prototype = { 8         constructor: Person; 9         sayName: function() {10             debug(this.name);11         };12     };13     var person2 = new Person('mackxu', 22, 'Software Engineer');14     var person3 = new Person('mackxu2', 23, 'Software Engineer');15     person2.sayName();        //mackxu16     person2.friends.push('wangwu');17     debug(person2.friends);        //['zhangsan', 'lisi', 'wangwu']18     debug(person3.friends);        //['zhangsan', 'lisi']
  • 动态原型模式

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

1     function Person(name, age, job) { 2         this.name = name; 3         this.age = age; 4         this.job = job; 5         this.friends = ['zhangsan', 'lisi']; 6          7         if (typeof this.sayName != 'function') { 8             Person.prototype.sayName = function() { 9                 debug(this.name);10             };11             Person.prototype.sayHi = function() {12                 debug("Hi");13             };14         }15     }16     var person2 = new Person('mackxu', 22, 'Software Engineer');17     person2.sayName();        //mackxu18     person2.sayHi();

    使用动态原型模式时,不能使用对象字面量重写原型。

  • 寄生构造函数模式

构造函数在不返回值的情况下,默认会返回新对象实例。而通过在构造函数的末尾添加return,可以重写调用构造函数时返回的值。

注意:返回的对象与构造函数或者与构造函数的原型属性之间没关系

1     function Person(name, age, job) { 2         var o = new Object(); 3         o.name = name; 4         o.age = age; 5         o.job = job; 6         o.sayName = function() { 7             debug(this.name); 8         }; 9         return o;10     }11     12     var person2 = new Person('mackxu', 22, 'Software Engineer');13     person2.sayName();        //mackxu14     15     function SpecialArray() {16         //创建数组17         var values = new Array();18         //添加值19         values.push.apply(values, arguments);20         //添加方法21         values.toPipedString = function() {22             return this.join('|');23         };24         return values;25     }    26     //此处new的作用是什么??27     var colors = new SpecialArray('red', 'blue', 'green');28     debug(colors.toPipedString());
  • 稳妥构造函数模式

禁止使用this和new,所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象

转载于:https://www.cnblogs.com/mackxu/archive/2012/11/12/2767181.html

你可能感兴趣的文章
RestTemplate 调用本地服务 connection refused
查看>>
.NET方向高级开发人员面试时应该事先考虑的问题
查看>>
并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
查看>>
台达PLC modbus 不支持04功能码
查看>>
python学习笔记--装饰器
查看>>
发布一个JavaScript工具类库jutil,欢迎使用,欢迎补充,欢迎挑错!
查看>>
discuz 常用脚本格式化数据
查看>>
Luogu P1991 无线通讯网
查看>>
(转载) 好的程序员到底好在哪里?
查看>>
MS CRM 2011 创建基于Fetch的报表 -- 进阶版
查看>>
zabbix 监控zookeeper
查看>>
trace与代码跟踪服务
查看>>
Fire!
查看>>
博客园是一个不错的学习交流的网站
查看>>
洛谷P2777
查看>>
Ajax
查看>>
VC++中CEdit控件实现回车换行
查看>>
bzoj2338[HNOI2011]数矩形 计算几何
查看>>
CodeForces - 732A Buy a Shovel 解题
查看>>
PHPStorm2017设置字体与设置浏览器访问
查看>>