资讯专栏INFORMATION COLUMN

js基础-八种创建对象方法

justCoding / 687人阅读

摘要:如果按照字面意思来理解,那么就是通过调用构造函数而创建的那个对象实例的原型对象。

创建对象方法

Object构造函数

对象字面量表示

工厂模式

构造函数模式

原型模式

构造函数模式与原型模式结合

动态原型模式

寄生构造函数模式

一、Object实例创建
var person1 = new Object();
person1.name = "bob";
person1.age = "22";
person1.job = "frontend";

person1.sayName = function () {
    console.log(this.name);
}

person1.sayName(); // bob
console.log(person1.age); // 22
二、对象字面量表示
var person2 = {
    name: "bob",
    age: 22,
    job: "frontend",
    sayName: function () {
        console.log(this.name);
    }
}
person2.sayName(); // bob
三、工厂模式
function createPerson(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function () {
        console.log(this.name);
    };
    return o;
}

var person1 = createPerson("bob", 22, "frontend");
var person2 = createPerson("lynn", 22, "doctor");

console.log(person1.name); // bob
console.log(person2.name); // lynn

优点:函数封装创建对象,无需写重复创建对象的代码

缺点:没有解决对象识别的问题(怎么样知道一个对象类型)

四、构造函数模式
function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function () {
        console.log(this.name);
    }
    
    /**
     * 与声明函数在逻辑上是等价的
       this.sayName = new Function("console.log(this.name)"); 
    */
}

var person1 = new Person("bob", 22, "frontend");
var person2 = new Person("lynn", 22, "doctor");

console.log(person1.name); // bob
console.log(person2.name); // lynn
优点:

没有显式地创建对象

直接将属性和方法赋给了this对象

没有return语句

缺点:

每个方法都要在每个实例上重新创建一遍

实现过程:

创建新的对象

将构造函数的作用域赋给新对象,因此this就指向了这个对象

执行构造函数的代码,为这个对象添加对象属性和方法

返回新的对象

person1person2分别保存着Person的一个不同的实例。这两个对象都有一个constructor(构造函数)属性,该属性指向Person

console.log(person1.constructor === Person); // true
console.log(person2.constructor === Person); // true

对象的constructor属性最初是用来标识对象类型的。但是,提到检测对象类型,还是instanceof操作符要更可靠一些

console.log(person1 instanceof Object); // true
console.log(person1 instanceof Person); // true
console.log(person2 instanceof Object); // true
console.log(person2 instanceof Person); // true

我们在这个例子中创建的所有对象既是Object的实例,同时也是Person的实例,这一点通过instanceof操作符可以得到验证,创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型

可以将构造函数当作函数
// 当作构造函数使用
var person = new Person("bob", 22, "frontend");
person.sayName(); //"Nicholas"

// 作为普通函数调用
Person("lynn", 22, "doctor"); // 添加到window
window.sayName(); //"Greg"

// 在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Kristen", 25, "Nurse");
o.sayName(); //"Kristen"
缺点优化

构造函数创建的对象方法,实际上执行多次函数创建,会导致不同的作用域链和标识符解析,如:

console.log(person1.sayName == person2.sayName);  //false

创建两个完成同样任务的Function实例的确没有必要;况且有this对象在,根本不用在执行代码前就把函数绑定到特定对象上面。因此,大可像下面这样,通过把函数定义转移到构造函数外部来解决这个问题。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}

// 把sayName函数抽离出外部函数
function sayName() {
    console.log(this.name);
}

存在问题:

所有被新创建出来的对象,都会指向全局作用域的sayName函数,如果定义N个方法,那么就要定义N个全局的方法,这就造成了封装性的瓶颈,不过可以使用原型模式来解决

五、原型模式
function Person() {
}

Person.prototype.name = "bob";
Person.prototype.age = 22;
Person.prototype.job = "frontend";
Person.prototype.sayName = function () {
    return this.name
}

var person1 = new Person();

console.log(person1.name); // bob
console.log(person1.age); // 22
console.log(person1.job); // frontend
console.log(person1.sayName()); // bob
console.log(person1.sayName === person2.sayName); // true

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。如果按照字面意思来理解,那么prototype就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

六、组合使用构造函数模式和原型模式
function Person(name, age, obj) {
    this.name = name;
    this.age = age;
    this.obj = obj;
}

Person.prototype = {
    constructor: Person,
    sayName: function () {
        console.log(this.name);
    }
}

var person1 = new Person("bob", 22, "frontend");
var person2 = new Person("lynn", 22, "doctor");

console.log(person1.name); // bob
console.log(person2.name); // lynn
console.log(person1.sayName === person2.sayName); // true
七、动态原型模式
function Person(name, age, obj) {
    this.name = name;
    this.age = age;
    this.obj = obj;

    console.log("typeof this.sayName: ", typeof this.sayName);
    // 检测sayName 是不是一个函数
    // 实际上只在当前第一次时候没有创建的时候在原型上添加sayName方法
    if (typeof this.sayName != "function") {
        Person.prototype.sayName = function () {
            return this.name;
        }
    }
}

var person1 = new Person("bob", 22, "frontend");
var person2 = new Person("lynn", 22, "doctor");

console.log(person1.name); // bob
console.log(person2.name); // lynn
console.log(person1.sayName()); // bob
console.log(person2.sayName()); // lynn
console.log(person1.sayName === person2.sayName); // true
八、寄生构造函数模式
function createPerson(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function () {
        console.log(this.name);
    };
    return o;
}

var person1 = new createPerson("bob", 22, "frontend");
var person2 = new createPerson("lynn", 22, "doctor");

console.log(person1.name); // bob
console.log(person2.name); // lynn

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95937.html

相关文章

  • JavaScript常用八种继承方案

    摘要:原型式继承利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型。其中表示构造函数,一个类中只能有一个构造函数,有多个会报出错误如果没有显式指定构造方法,则会添加默认的方法,使用例子如下。 (关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导)showImg(https://segmentfault.com/img/rem...

    wpw 评论0 收藏0
  • Vue组件之间通信的八种方式

    摘要:使用也有很长一段时间但是一直以来都没对其组件之间的通信做一个总结这次就借此总结一下。引用信息将会注册在父组件的对象上。 使用Vue也有很长一段时间,但是一直以来都没对其组件之间的通信做一个总结,这次就借此总结一下。 父子组件之间的通信 1)props和$emit 父组件通过props将数据下发给props,子组件通过$emit来触发自定义事件来通知父组件进行相应的操作 具体代码如下: ...

    klinson 评论0 收藏0
  • 八种js交换两个变量的值方案总结

    摘要:假定期望交换和的值序号实现方案中间变量备注按位操作符只适用类型只适用类型有脑洞先执行对象解构赋值推荐数组解构赋值简书首发转载请注明来自简书 假定let a = 1,b=10;期望交换a和b的值 序号 实现方案 中间变量? 备注 1 let c; c = a; a = b; b = c; ✅ 2 a ^= b; b ^=a; a ^=b MDN-按位操作符, 只适...

    LiveVideoStack 评论0 收藏0
  • Java 总结

    摘要:中的详解必修个多线程问题总结个多线程问题总结有哪些源代码看了后让你收获很多,代码思维和能力有较大的提升有哪些源代码看了后让你收获很多,代码思维和能力有较大的提升开源的运行原理从虚拟机工作流程看运行原理。 自己实现集合框架 (三): 单链表的实现 自己实现集合框架 (三): 单链表的实现 基于 POI 封装 ExcelUtil 精简的 Excel 导入导出 由于 poi 本身只是针对于 ...

    caspar 评论0 收藏0
  • OpenCV实战 | 八种目标跟踪算法

    摘要:目标追踪首先,我们会大致介绍八种建立在上的目标跟踪算法。词典包含了种的目标追踪器行。它将目标追踪器的命令行参数字符串映射到实际的追踪器函数上。其中行里的目的是根据追踪器命令行参数以及从得来的相关重要信息。 虽然我们熟知的的质心追踪器表现得很好,但它需要我们在输入的视频上的每一帧运行一个目标探测器。对大多数环境来说,在每帧上进行检测非常耗费计算力。所以,我们想应用一种一次性的目标检测方法,然后...

    shevy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<