JavaScript创建对象的几种方式及关于this指向问题

目录
  • 工厂模式
  • 构造函数模式
    • 关于 this
  • 原型模式

工厂模式

工厂模式一般用于抽象创建特定对象的过程,是按照特定接口创建对象的方式。

function createPerson(name, age) {
    let o = {};
    o.name = name;
    0.age = age;
    o.study = function() {
        console.log(`${this.name} is studying`)
    }
    return o
}
const p1 = createPerson('张三', 18)
const p2 = createPerson('李四', 20)
p1.study() // 张三 is studying

值得一提的是,如果在 createPerson 函数中,o.study 改为箭头函数,那么打印的 this 会发生改变,这是因为箭头函数发生了 this 指向的问题。

工厂模式的优点: 在 createPerson 中,可以用不同的参数多次调用工厂函数,每次都会返回包含特定参数和一个方法的对象。可以解决创建多个类似对象的问题。

工厂模式的缺点:

  • 1. 没有解决对象标识问题。
  • 2. 每次创建对象,都会创建一个公共的方法,而方法也是对象,所以造成内存浪费。

构造函数模式

在 JS 中, 构造函数是用于创建特定类型对象的。像 ObjectArray 这样的原生构造对象,运行时,可以直接在执行环境中运行。当然也可以自定义构造函数,以函数的形式为自己的对象类型定义属性和方法。

function Student(name, age) {
    this.name = name;
    this.age = age;
    this.study = function() {
        console.log(`${this.name} is studying`)
    }
}
const p1 = new Student('张三', 18)
const p2 = new Student('李四', 20)

通过上面的代码,可以实现和工厂模式一样的效果。但是值得注意的是: 如果这里的 study 函数变为箭头函数, this 的指向是不会发生变化的。

如同上面的代码,如果调用构造函数,就必须使用 new 关键字,在这个过程中,构造函数会做四件事情:

  • 在内存中创造一个新的对象
  • 将这个新的对象的隐式原型 __proto__ 赋值为该构造函数的显示原型 prototype
  • 构造函数的内部的 this 被赋值为这个新的对象(给新对象添加新的属性)
  • 执行构造函数中的代码,并且判断有无对象返回值,如果存在,则返回这个返回值,否则返回这个新的对象
  • 构造函数的优缺点: 首先,构造函数解决了对象的标识问题,但是如果构造函数中存在着函数,那么每次创建一个实例,就相当于函数也被重新创造了一遍,因为在JS中函数也是相当于对象,造成了对空间的浪费。

关于 this

在标准函数中, this 引用的是把函数当成方法调用的上下文对象,这个时候常称其为 this。

我们在上文说过,工厂模式和构造函数模式,其内部如果出现箭头函数,那么 this 的指向会出现不同,这是因为,箭头函数中不存在 this , 箭头函数中的 this会保留定义该函数的上下文this 到底引用哪个对象必须到函数调用时,才会确定, 在工厂模式时, 虽然通过p1.study(),进行调用,但是由于箭头函数内部没有 this,所以向上查找,找到function createPerson 函数, 绑定 window, 而在构造函数模式中this 赋值给了这个新的对象,相当于箭头函数的this, 就是这个新的对象,也就是之后的实例。

可能,通过上面的描述,很多同学仍然对下面箭头函数中的this,会保留定义该函数的上下文不太理解,我列举一个例子。

// 工厂模式
function createPerson(name, age) {
    let o = {};
    o.name = name;
    o.age = age;
    o.study = () => {
        console.log(`${this.name} is studying`)
    }
    return o
}

const obj = {
    name: '张三'
}

const p1 = createPerson.call(obj, '李四', 20) // createPerson 绑定 obj, 那么箭头函数也会绑定 obj
p1.study() // 所以这里的输出是 张三 is studying,而不是 undefined

原型模式

每个函数都会创建一个 prototype 属性,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。使用原型对象的好处是,在它上面定义的属性和方法可以被对象实例共享。原来在构造函数中直接赋值给对象实例的值,可以直接赋值给他们的原型。

function Student() {}
Student.prototype.name = '张三';
Student.prototype.age = 20;
Student.prototype.friends = ['ls', 'ww'];
Student.prototype.study = function() {
    console.log(`${this.name} is studying`)
}

const p1 = new Student()
const p2 = new Student()

通过上面创建的p1, p2,共用了Student原型上的属性,相当于创造了两个拥有相同属性的不同对象。同理,如果上面的 study 改为了箭头函数,大家应该也能知道 this 绑定的是谁了吧。(Tip: new 和 显示绑定不可以同时使用)

原型模式的优缺点 : 首先原型模式解决了上两种模式造成的空间浪费问题,但是,其属性都是共享的,所以一般来说,原型模式不会单独去使用。

(0)

相关推荐

  • JS创建对象常用设计模式工厂构造函数及原型

    目录 引言 工厂模式 构造函数模式 原型模式 结语 引言 很多工友们都说:设计模式根本用不到,然而它其实时刻就在我们身边,像王国维所说:众里寻他千百度,蓦然回首,那人正在灯火阑珊处. 工厂模式 什么是工厂模式?其实就字面意思,在现实社会生活中,市场通过不同工厂加工成不同的产品. 转化成 JS 代码就是这样的: // 汽车工厂 function carFactory(brand, price, district) { let o = new Object(); o.brand= brand; o.

  • JavaScript 中this指向问题案例详解

    总结 全局环境 ➡️ window 普通函数 ➡️ window 或 undefined 构造函数 ➡️ 构造出来的实例 箭头函数 ➡️ 定义时外层作用域中的 this 对象的方法 ➡️ 该对象 call().apply().bind() ➡️ 第一个参数 全局环境 无论是否在严格模式下,this 均指向 window 对象. console.log(this === window) // true // 严格模式 'use strict' console.log(this === window

  • JS对象创建与继承的汇总梳理

    目录 引言 对象创建 工厂函数 构造函数 构造+原型 工厂+构造+原型 ES6 class 对象与函数 小结 引言 在 6 月更文中零零散散讲了 JS 的对象创建和对象继承,有工友对此还是表示疑惑,要注意:这是两个不同但又相关的东西,千万别搞混了! 这些文章是: 蓦然回首,“工厂.构造.原型”设计模式,正在灯火阑珊处 JS精粹,原型链继承和构造函数继承的 “毛病” “工厂.构造.原型” 设计模式与 JS 继承 JS 高级程序设计 4:class 继承的重点 JS class 并不只是简单的语法糖

  • java链式创建json对象的实现

    目录 1.假设我们要创建一个json对象格式如下: 2.往常创建JSON语法: 3.解决方案——链式创建JSON: 4.实现多级JSON 5.YtJSONObject类源码 我们主要介绍一下:java中如何通过最简单的方式实现链式创建json对象,解决创建json代码臃肿的问题. 1.假设我们要创建一个json对象格式如下: { "code": 0, "msg": "SUCCESS" } 2.往常创建JSON语法: java中传统的创建json一

  • JS创建对象的四种方式

    目录 1.通过字面量的方式去创建对象 2.使用new字符创建对象 3.自定构造函数创建对象 4.工厂模式创建对象 创建对象的4种方式: 1.字面量的方式去创建对象 2.使用new字符创建对象 3.自定义构造函数 4.工厂模式创建对象 对象是指:具有属性和方法 1.通过字面量的方式去创建对象 var person1={ name:'柯南', age:12, sex:'男', eat:function(){ console.log("我饿了,想吃饭") }, say:function(){

  • 详解JavaScript原型对象的this指向问题

    目录 一.this指向 二.修改this指向 1.call()方法 2.apply()方法 总结 一.this指向 构造函数中的this 指向实例对象.那么原型对象this的指向呢? 如下: function Student(age,name){ this.age = age; this.name = name; } var that; Student.prototype.score = function(){ console.log('孩子们成绩都很好!'); that = this; } v

  • JavaScript函数this指向问题详解

    目录 一. 函数内 this 的指向 1.普通函数 2.构造函数 3.对象方法 4.事件绑定方法 5.定时器函数 6.立即执行函数 二.改变函数内部 this 指向 1.call 方法 2.apply 方法 3.bind 方法 三.call apply bind 总结 1.相同点 2.不同点  3.应用场景  总结 一. 函数内 this 的指向 这些 this的指向,是当调用函数的时候确定的. 调用方式的不同决定了this 的指向不同,一般指向调用者. 现在我们来具体看看吧! 1.普通函数 f

  • JavaScript中的this指向问题详解

    前言 相信我,只要记住本文的 7️⃣ 步口诀,就能彻底掌握 JS 中的 this 指向. 先念口诀:箭头函数.new.bind.apply 和 call.欧比届点(obj.).直接调用.不在函数里. 按照口诀的顺序,只要满足前面某个场景,就可以确定 this 指向了. 接下来按照口诀顺序对它们进行详解,文中示例代码都运行在 Chrome 的 Console 控制台中. 文末有精心准备的练习题,用于检验学习成果,别忘了试试~ 1. 箭头函数 箭头函数排在第一个是因为它的 this 不会被改变,所以

  • JavaScript函数中this指向问题详解

    this关键字 哪个对象调用函数,函数里面的this指向哪个对象. **严格模式下:**在全局环境中,this指向的是undefined **非严格模式下:**在全局环境中,this指向的是window 全局定义的函数直接调用,this => window function fn(){ console.log(this); // 此时 this 指向 window } fn(); // 相当于 window.fn() 对象内部的函数调用,this => 调用者 var obj = { fn:f

  • JavaScript创建对象的几种方式及关于this指向问题

    目录 工厂模式 构造函数模式 关于 this 原型模式 工厂模式 工厂模式一般用于抽象创建特定对象的过程,是按照特定接口创建对象的方式. function createPerson(name, age) { let o = {}; o.name = name; 0.age = age; o.study = function() { console.log(`${this.name} is studying`) } return o } const p1 = createPerson('张三',

  • JavaScript创建对象的七种方式(推荐)

    JavaScript创建对象的方式有很多,通过Object构造函数或对象字面量的方式也可以创建单个对象,显然这两种方式会产生大量的重复代码,并不适合量产.接下来介绍七种非常经典的创建对象的方式,他们也各有优缺点. 工厂模式 function createPerson(name, job) { var o = new Object() o.name = name o.job = job o.sayName = function() { console.log(this.name) } return

  • JavaScript创建对象的七种方式全面总结

    JavaScript创建对象的方式有很多,通过Object构造函数或对象字面量的方式也可以创建单个对象,显然这两种方式会产生大量的重复代码,并不适合量产.接下来介绍七种非常经典的创建对象的方式,他们也各有优缺点 工厂模式 function createPerson(name, job) { var o = new Object() o.name = name o.job = job o.sayName = function() { console.log(this.name) } return

  • 学习javascript面向对象 掌握创建对象的9种方式

    本文为大家分享了javascript创建对象的9种方式,供大家参考,具体内容如下 [1]使用Object构造函数 [缺点]使用同一个接口创建很多对象,会产生大量重复代码 var person = new Object(); person.name = "Nicholas"; person.age = 29; person.job = "Software Engineer"; person.sayName = function(){ alert(this.name);

  • js面向对象之常见创建对象的几种方式(工厂模式、构造函数模式、原型模式)

    在上篇文章给大家介绍了javascript面向对象基础,本篇文章继续深入学习javascript面向对象,JS的语法非常灵活,简单的对象创建就有好几种不同的方法.这些过于灵活的地方有时候确实很让人迷惑,那么今天我们就来梳理一下JS中常用的创建对象的几种方法吧. 前言 虽然使用 Object构造函数 或者使用 对象字面量 可以很方便的用来创建一个对象,但这种方式有一个明显的缺点:使用一个接口创建多个对象会产生很多冗余的代码.因此为了解决这个问题,人们开始使用以下几种方式来常见对象. 工厂模式 该模

  • javascript创建对象的几种模式介绍

    在js中有几种模式可以创建对象,通过对象操作所包含的属性与方法. 一般来说,构造函数名称的第一个字母为大写字母,非构造函数名称的第一个字母为小写字母,当然,构造函数与一般函数唯一的区别只是调用的方式不同而已,所以任何函数只要通过new来调用,那它就可以作为构造函数,若不通过new来调用,则与一般函数一样. 谈谈我对这几种模式的理解: 工厂模式:创建一个一般函数,在函数里创建一个Object对象,为这个对象增添属性与方法,同时赋予其值,最后返回对象.无法识别对象类型. 构造函数模式:创建构造函数,

  • js中创建对象的几种方式

    前言 不管是哪门语言,千变万化不离其宗,深入理解其本质,方能应用自如.对应到js,闭包,原型,函数,对象等是需要花费大功夫思考.理解的.本文穿插了js原型和函数的相关知识,讨论了批量创建对象的几种方式以及它们的优缺点. 正文 说起创建对象,最容易想到的便是通过对象字面量方式直接定义一个对象吧,但这种方式只能创建少量,单独且相互间无联系的对象.若要批量创建对象,该如何? 工厂模式 工厂模式非常直观,将创建对象的过程抽象为一个函数,用函数封装以特定接口创建对象的细节.如下所示: function c

  • JavaScript创建对象的四种常用模式实例分析

    本文实例讲述了JavaScript创建对象的四种常用模式.分享给大家供大家参考,具体如下: 这里介绍了javascript中创建对象常用的几种模式,包括:工厂模式,构造函数模式,原型模式,组合构造函数与原型的模式,动态原型模式. 一.工厂模式 看如下代码: function getMySon(name,sex){ var o={}; o.name=name; o.sex=sex; o.sayName = function(){ alert(this.name); } return o; } so

  • 详解js创建对象的几种方式和对象方法

    这篇文章是看js红宝书第8章,记的关于对象的笔记(第二篇). 创建对象的几种模式: 工厂模式: 工厂是函数的意思.工厂模式核心是定义一个返回全新对象的函数. function getObj(name, age) { let obj = {} obj.name = name obj.age = age return obj } let person1 = getObj("cc", 31) 缺点:不知道新创建的对象是什么类型 构造函数模式: 通过一个构造函数,得到一个对象实例. 构造函数和

  • Spring IOC创建对象的两种方式

    IOC创建对象的方式 一. 使用无参构造创建对象(默认方式) 创建实体类 注意:属性必须要有set方法,来完成注入 public class User { private String name; public User() { System.out.println("执行了User类的无参构造方法~"); } public User(String name){ this.name = name; System.out.println("执行了User类的有参构造方法&quo

随机推荐