1. 简单方式创建对象


  1. // 字面量方式创建对象
  2. var person1 = {
  3. name: "xyc",
  4. age: 23,
  5. sayHi: function() {
  6. console.log(name);
  7. }
  8. };
  9.  
  10. // Object方式创建对象
  11. var person2 = new Object();
  12. person2.name = "lxy";
  13. person2.age = 18;
  14. person2.sayHi = function() {
  15. console.log(person2.name);
  16. }

虽然Object构造函数或对象字面量都可以用来创建单个对象,但这些方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码,如上面的代码,每创建一个类似的person对象,就会重复上面的写法,代码较为冗余

为了解决这个问题(代码重复),下面引入工厂模式 ==>

2. 工厂模式创建对象


  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. alert(this.name);
  8. };
  9. return o;
  10. }
  11. var person1 = createPerson("Nicholas", 29, "Software Engineer");
  12. var person2 = createPerson("Greg", 27, "Doctor");

通俗的解释:工厂模式就是利用了函数的封装调用,类比工厂材料==>成品的过程,完成入口参数==>对象的过程,函数可以无数次的生成,因此能够避免上面产生大量重复代码的情况。工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)

为解决这个问题(对象识别),下面引入构造函数模式

3. 构造函数创建对象


3.1 构造函数与普通函数的区别

  1. 命名规则:构造函数一般是首字母大写,普通函数遵照小驼峰式命名法
  2. 函数调用
    构造函数:
    (1)new fn( )
    (2)构造函数内部会创建一个新的对象,即f的实例
    (3)函数内部的this指向 新创建的f的实例
    (4)默认的返回值是f的实例
    普通函数:
    (1)fn( )
    (2)在调用函数的内部不会创建新的对象
    (3)函数内部的this指向调用函数的对象(如果没有对象调用,默认是window)
    (4)返回值由return语句决定
  3. 构造函数的返回值
    有一个默认的返回值,新创建的对象(实例),当手动添加返回值后(return语句):
    (1)返回值是基本数据类型-->真正的返回值还是那个新创建的对象(实例)
    (2)返回值是复杂数据类型(对象)-->真正的返回值是这个对象

    1. function foo() {
    2. var f2 = new foo2();
    3. console.log(f2); // {a: 3}
    4. console.log(this); // window
    5. return true;
    6. }
    7. function foo2() {
    8. console.log(this); // foo2类型的对象 不是foo2函数
    9. return {a: 3};
    10. }
    11. var f1 = foo();
    12. console.log(f1); // true

3.2 new 操作符作用

使用new操作符调用构造函数会经历下面几个步骤:
(1)创建一个以这个函数为原型的空对象.
(2)将函数的 prototype 赋值给对象的 proto 属性
(3)将对象作为函数的 this 传进去。如果有 return 出来东西是对象的话就直接返回 return 的内容,没有的话就返回创建的这个对象

  1. function NewFunc(func){
  2. var ret = {};
  3. if (func.prototype !== null) {
  4. ret.__proto__ = func.prototype;
  5. }
  6. var ret1 = func.apply(ret, Array.prototype.slice.call(arguments, 1));
  7. if ((typeof ret1 === "object" || typeof ret1 === "function") && ret1 !== null) {
  8. return ret1;
  9. }
  10. return ret;
  11. }

普通函数的作用主要是封装作用,能够在作用域内多处调用而已

3.3 构造函数解决对象识别

创建自定义的构造函数意味着可以通过 instanceof 将它的实例标识为一种特定的类型

  1. function Person(name,age,job){
  2. this.name = name;
  3. this.age = age;
  4. this.sayHi = function(){
  5. console.log(this.name);
  6. }
  7. }
  8.  
  9. var person1 = new Person('xyc', 23);
  10. var person2 = new Person('lxy', 22);
  11.  
  12. console.log(person1 instanceof Person); //true
  13. console.log(person2 instanceof Person); //true
  14. console.log(person1 instanceof Object); //true 因为Person继承自Object,所以这里一样成立.

3.4 缺陷

构造函数创建对象的方式解决了代码重复对象识别的问题,但是创建的对象中含有方法时,每实例化一个Person,就会产生一个方法,也就是一个对象,每个对象分别占据内存。因此,构造函数创建对象的方式存在内存大量占用的风险

利用原型共享的特性,下面引入原型模式

4. 原型创建对象


  1. function Person(){}
  2. Person.prototype = {
  3. constructor: Person,
  4. name : "Nicholas",
  5. age : 29,
  6. job : "Software Engineer",
  7. friends : ["Shelby", "Court"],
  8. sayName : function () {
  9. alert(this.name);
  10. }
  11. };
  12.  
  13. var person1 = new Person();
  14. var person2 = new Person();
  15.  
  16. person1.sayName(); //"Nicholas"
  17. person2.sayName(); //"Nicholas"
  18.  
  19. person1.friends.push("Van");
  20. alert(person1.friends); //"Shelby,Court,Van"
  21. alert(person2.friends); //"Shelby,Court,Van"
  22. alert(person1.friends === person2.friends); //true

原型创建对象的方式将属性和方法都存在与原型中,也就是说,只要通过这种形式创建的对象都会共享这些属性和对象,相对于方法共享这是我们乐于看到的,但是属性共享让每个实例缺失了“个性”;另外对于引用类型的属性共享时,如上面的例子,多个实例对引用类型的操作会被篡改

实例一般都要有属于自己的全部属性,这也决定了原型创建方式的局限性。下面引入非常经典的对象创建方式

5. 构造函数+原型创建对象(重点)


组合构造函数模式与原型模式:构造函数模式用于定义实力属性,而原型模式用于定义方法和共享的属性

  1. function Person(name, age, job){
  2. this.name = name;
  3. this.age = age;
  4. this.job = job;
  5. this.friends = ["Shelby", "Court"];
  6. }
  7.  
  8. Person.prototype = {
  9. constructor : Person,
  10. sayName : function(){
  11. alert(this.name);
  12. }
  13. }
  14.  
  15. var person1 = new Person("Nicholas", 29, "Software Engineer");
  16. var person2 = new Person("Greg", 27, "Doctor");
  17.  
  18. person1.friends.push("Van");
  19. alert(person1.friends); //"Shelby,Count,Van"
  20. alert(person2.friends); //"Shelby,Count"
  21. alert(person1.friends === person2.friends); //false
  22. alert(person1.sayName === person2.sayName); //true

这种方式创建的实例对象,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存;另外,这种方式还支持相构造函数传递参数,解决了上面的各种问题!

6. Object.create(ES5)

在ES5之前,只能使用new来实现原型链集成。总而言之Object.create()和字面量对象应该替换new object()方法。
Object.create()可以接收两个参数:提供原型的对象,可选属性对象(这个对象包含对新创建对象的配置)。

  1. var Car = {
  2. drive: function (miles) {
  3. return this.odometer += miles;
  4. }
  5. };
  6. var tesla = Object.create(Car, {
  7. 'odometer': {
  8. value: 0,
  9. enumerable: true
  10. }
  11. ));
  12.  
  13. //输出10
  14. console.log(tesla.drive(10));

总结

javascript中创建对象的方式及优缺点(一)的更多相关文章

  1. javascript中创建对象的方式及优缺点(二)

    一.工厂模式 流程: 定义一个函数,函数返回对象. 适用场景: 需要创建多个对象,都是Object类型. 优点:完成了返回一个对象的要求. 缺点: 对象没有一个具体的类型,无法通过constructo ...

  2. javascript中创建对象的方式总结

    javascript中创建对象的方式总结 具体代码如下: //创建对象的方式: //创建方式一 var person=new Object(); person.name='jack'; person. ...

  3. javascript中各种继承方式的优缺点

    javascript中实现继承的方式有很多种,一般都是通过原型链和构造函数来实现.下面对各种实现方式进行分析,总结各自的优缺点. 一 原型继承 let Super = functioin(name = ...

  4. JavaScript中创建对象的三种方式!

    JavaScript中创建对象的三种方式! 第一种 利用对象字面量! // 创建对象的三种方式! // 1 对象字面量. var obj = { // 对象的属性和方法! name: 'lvhang' ...

  5. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  6. javascript中创建对象的几种不同方法

    javascript中创建对象的几种不同方法 方法一:最直白的方式:字面量模式创建 <script> var person={ name:"小明", age:20, s ...

  7. javascript 中继承实现方式归纳

    转载自:http://sentsin.com/web/1109.html 不同于基于类的编程语言,如 C++ 和 Java,javascript 中的继承方式是基于原型的.同时由于 javascrip ...

  8. javascript中创建对象和实现继承

    # oo ##创建对象 1. 原型.构造函数.实例之间的关系 * 原型的construct->构造函数:调用isPrototypeOf(obj)方法可以判定和实例的关系:  * 构造函数的pro ...

  9. JavaScript 常见创建对象的方式

    JavaScript 有哪几种创建对象的方式? javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON:但写法有很多种,也能混合使用. (1)对象字面量的方式 ...

随机推荐

  1. 使用Python基于百度等OCR API的文字识别

    百度OCR Baidu OCR API:一定额度免费,目前是每日500次 Python SDK文档:https://cloud.baidu.com/doc/OCR/OCR-Python-SDK.htm ...

  2. Spring的事务传播机制实例 (转)

    1,Propagation.REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中.详细解释在代码下方. 实例 员工service @Service public ...

  3. Java后端技术面试汇总(第五套)

    1.Java相关 • 乐观悲观锁的设计,如何保证原子性,解决的问题:• char和double的字节,以及在内存的分布是怎样:• 对象内存布局,然后讲下对象的死亡过程?• 对象头,详细讲下:• syn ...

  4. 07 Python中zip(),map(),filter(),reduce()用法

    一. zip() zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 ...

  5. html/css弹性布局的几大常用属性详解

    弹性布局的名称概念: 1.容器:需要添加弹性布局的父元素:项目:弹性布局容器中的每一个子元素,称为项目. 2.主轴:在弹性布局中,我们会通过属性规定水平/垂直方向(flex-direction)为主轴 ...

  6. 关于Linux防火墙的问题以及关闭,试一下这四条命令

    关闭防火墙,依次执行以下四条命令 临时服务 service firewalld stop 永久关闭 chkconfig iptables off 列出所有规则 iptables -L 清除所有规则,可 ...

  7. centos7.2升级openssh7.9p1

    Centos7.2版本yum升级openssh版本最高到7.4,想要升级到更高的版本需要重新编译 一.查看当前openssh版本: [root@localhost ~]# ssh -VOpenSSH_ ...

  8. verilog 实用的小技巧

    (之后还会持续的更新) 移位操作的实现: verilog有一种非常简单的移位操作实例如下: reg [3:0] source; reg out; {out,source[3:0]}={source[3 ...

  9. Java并发(基础知识)—— Executor框架及线程池

    在Java并发(基础知识)—— 创建.运行以及停止一个线程中讲解了两种创建线程的方式:直接继承Thread类以及实现Runnable接口并赋给Thread,这两种创建线程的方式在线程比较少的时候是没有 ...

  10. 标准C语言(12)

    一个存储区的地址应该是它自身大小的整数倍(双精度浮点类型存储区的地址只需要是4的整数倍),这个规则叫数据对齐,结构体内部的存储区通常也需要遵守数据对齐的规则,数据对齐有可能导致结构体相邻子存储区之间有 ...