当前位置: 首页 > news >正文

javaScript创建对象的方法

一、使用Object构造函数

var person = new Object();
person.name = 'Tom';
person.age = 18;
person.say = function(){
    console.log(this.name + ' ' + this.age);
}
复制代码

二、对象字面量方式

var person = {
    name: 'Tom',
    age: 18,
    say: function(){
        console.log(this.name + ' ' + this.age);
    }
}
复制代码

三、工厂模式

function person(name, age) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.say = function() {
        console.log(this.name + ' ' + this.age);
    }
    return o;
}
var person1 = person('Tom', 18);
var person2 = person('Harry', 28);
复制代码

四、构造函数模式

function Person(name, age){
    this.name = name;
    this.age = age;
    this.say = function() {
        console.log(this.name + ' ' + this.age);
    }
}
var person1 = new Person('Tom', 18);
var person2 = new Person('Harry', 28);
复制代码

构造函数模式同工厂模式的不同之处:

  • 没有显示的创建对象
  • 直接将属性和方法赋值给this对象
  • 没有明显的return语句
  • 同时按照惯例,构造函数首字母大写,非构造函数首字母不大写

要创建一个构造函数的实例需要使用 new 操作符,这种方式调用构造函数其实经历了如下几个步骤:

  • 创建一个新对象
  • 将构造函数的作用域赋给这个新对象,同时 this 指向这个新创建的对象
  • 执行构造函数,为新对象添加属性
  • 返回新对象

上面的 person1 和 person2 为 Person 构造函数的两个不同实例,它们分别有一个constructor属性,指向Person。检查是否为某个构造函数的实例可以用 instanceof 操作符。

person1.constructor === Person;     //true
person2.constructor === Person;     //true

person1 instanceof Person;     //true
person2 instanceof Person;     //true
person1 instanceof Object;     //true
person2 instanceof Object;     //true
复制代码

构造函数本身也是函数,当它使用 new 操作符来调用时就说构造函数,如果不使用 new 操作符来调用就是普通的函数。

//作为普通函数调用,此时的方法加在了全局对象上
Person('Bob', 26);
window.say();       //Bob 26

//在另一个对象的作用域中调用,调用后 o 就有了所有的属性和方法
var o = new Object();
Person.call(o, 'Greg', '30');
o.say();            //Greg 30
复制代码
构造函数的问题 —— 在每创建一个构造函数的实例时都要重创一遍方法。

五、原型模式

我们在创建一个函数时,都会有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含可以由由特定类型的所有实例共享的属性和方法。如下例子所示:

function Person(){}
Person.prototype.name = 'John';
Person.prototype.age = 20;
Person.prototype.say = function() {
    console.log(this.name + ' ' + this.age);
};

var person1 = new Person();
person1.say();
var person2 = new Person();
person2.say();
复制代码

创建一个新函数时就会创建一个该函数的prototype属性,如上例子中,Person构造函数有一个prototype属性,该原型对象会获得一个constructor(构造函数)属性,这个属性指回构造函数,即Person.prototype.constructor指回Person。通过构造函数我们可以继续为原型对象添加属性和方法。

当调用构造函数创建实例时,该实例内部将包含一个指针([[Prototype]]),指向构造函数的原型对象。我们可以通过isPrototypeOf()方法来测试。使用Object.getPrototypeOf()方法可以返回[[Prototype]]的值。

Person.prototype.isPrototypeOf(person1);    //true
Person.prototype.isPrototypeOf(person2);    //true
Object.getPrototypeOf(person1) === Person.prototype;    //true
Object.getPrototypeOf(person1).name;        //'John'
复制代码

我们可以为实例添加与原型中同名的属性来屏蔽原型中的属性的值,同时也可以用delete 操作符删除实例属性,从而重新访问原型中的属性。 Object的hasOwnProperty()方法可以检测一个属性是存在于实例中还是原型中。而使用 in 操作符无论是在原型中还是实例中,只要能找到都返回true。 我们也可以用Object.keys()方法来查看传入对象的所有可枚举的属性。而Object.getOwnPropertyNames()方法会返回传入对象的所有属性,无论能不能枚举。

原型对象的问题跟它的共享性有关,当创建一个对象的两个实例,改变一个实例的属性,另一个会受影响。

function Person(){}
Person.prototype.name = 'John';
Person.prototype.age = 20;
Person.prototype.friends = ['Bob', 'Harry']
Person.prototype.say = function() {
    console.log(this.name + ' ' + this.age);
};

var person1 = new Person();
var person2 = new Person();
person1.friends.push('Lisa');
person2.friends;        //'Bob', 'Harry', 'Lisa'
复制代码

如若此时只是想给person1的friends增加单独的值,就不能达到预期结果。

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

function Person(name, age){
    this.name = name;
    this.age = age;
    this.friends = ['Bob', 'Harry']
}

Person.prototype = {
    constructor: Person,
    say: function() {
        console.log(this.name + ' ' + this.age);
    }
};

var person1 = new Person('John', 20);
var person2 = new Person('Lee', 22);
person1.friends.push('Lisa');
person2.friends;        //'Bob', 'Harry'
复制代码

以上方式为实例属性在构造函数中定义,所有实例共享的属性constructor和方法在原型中定义。

七、动态原型模式

function Person(name, age){
    this.name = name;
    this.age = age;
    this.friends = ['Bob', 'Harry'];
    if(typeof this.say != 'function'){
        Person.prototype.say = function() {
            console.log(this.name + ' ' + this.age);
        }
    }
}

var g = new Person('Lucy', 18);
g.say();      //Lucy 18  
复制代码

相关文章:

  • Jmeter+Ant+Jenkins接口自动化测试框架搭建for Windows
  • ADO.Net中DataSet的应用
  • 整顿乱象后,区块链未来走向何方?
  • python列表排序
  • https://yq.aliyun.com/live/482
  • spring-AOP(二)实现原理之AspectJ注解方式
  • 区块链软件公司:区块链的原理
  • mysql 常见问题
  • 用友云实名认证,了解一下
  • 详解如何用爬虫程序采集新闻信息数据(以中国日报为例)
  • mongodb分组统计,并且删除重复数据
  • linux使用操作的常用命令
  • python - unitest - 实战题目
  • Linux磁盘空间占满问题快速定位
  • 4个顶级开源JavaScript图表库
  • Centos6.8 使用rpm安装mysql5.7
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Git的一些常用操作
  • Java编程基础24——递归练习
  • Java读取Properties文件的六种方法
  • java中的hashCode
  • V4L2视频输入框架概述
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 分布式任务队列Celery
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 深度解析利用ES6进行Promise封装总结
  • 说说动画卡顿的解决方案
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ionic入门之数据绑定显示-1
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 正则表达式-基础知识Review
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • #传输# #传输数据判断#
  • #每日一题合集#牛客JZ23-JZ33
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (LeetCode C++)盛最多水的容器
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)可以带来幸福的一本书
  • .net core webapi 大文件上传到wwwroot文件夹
  • .Net MVC + EF搭建学生管理系统
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .net 微服务 服务保护 自动重试 Polly
  • .NET设计模式(11):组合模式(Composite Pattern)
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节