资讯专栏INFORMATION COLUMN

深入浅出面向对象和原型【概念篇2】

DevTTL / 2412人阅读

摘要:墙裂建议您在看这篇文章之前阅读一遍我之前写的文章深入浅出面向对象和原型概念篇,因为此篇文章涉及到不少相关概念都在上篇文章里啦简单复习对象对象是老生常谈的概念了,在这里我们来简单复习一下对象内储存一个对象对象是一个储存一系列无序键值对的集合的

墙裂建议您在看这篇文章之前阅读一遍我之前写的文章深入浅出面向对象和原型【概念篇1】,因为此篇文章涉及到不少相关概念都在上篇文章里啦
1.1 简单复习对象

对象是老生常谈的概念了,在这里我们来简单复习一下

var obj = {
        a: 1, 
        b: "hello",
        c: true,
        d: function () {
            console.log("hello")
        },
        e: {
            e_1: "对象内储存一个对象"
        }
    }

对象是一个储存一系列无序 key: value【键值对】 的集合的容器

注意:核心是要将对象作为一个容器看待

使用对象作为容器的这个特性我们可以进行封装,这会产生两个好处

让我们的代码变得优雅、易读

规避全局变量

1.2 通过构造函数创建对象 1.2.1 关于function的额外知识

function作为构造函数(通过new操作符调用)的时候会 返回 一个类型为function的对象

function可以接受参数,可以根据参数来创建 相同类型不同值 的对象

function实例作用域内有一个constructor属性,这个属性就可以指示其构造器

1.2.2 学会使用 new Function

new 运算符接受一个函数 F 及其参数:new F(arguments...)

创建类的实例——这步是把一个空的对象的__proto__属性设置为 F.prototype

初始化实例——函数 F 被传入参数并调用,关键字 this 被设定为该实例

返回实例

    function People(name) {
        this.name = name
        this.sayName = function () {
            console.log(name)
        }
        // 一般在这个函数里不要 return
        // 如果return引用类型的话,等于把return的值赋值给p1
    }

    People() // this指向全局变量,name和sayName成为了全局变量的属性

    var p1 = new People("sad")
    // 第一步:instance = {} 创建了一个类的实例 —— 空对象,并且将空的对象的__proto__属性设置为 F.prototype,也就是说
    // 第二步:执行函数People(),并传入参数"sad",并将this指向p1
    // 第三步:return instance【实例】 , 即把instance赋值给p1

    // 请注意 People()是一个函数,new People()是构造函数

    var p2 = new People("angry")
1.2.3 instanceof

instance 的中文意思为 实例
那么 instanceof 自然就是用来判断对象是否为某个类型的实例

    console.log(p1 instanceof People) // true
    // 意思是判断 对象(p1)是否为某个类型(People)的实例
    // p1 是由 People 构建出来的,自然是People的实例,返回为true

但需要注意的是,instanceof 运算符的工作原理是检测 类的prototype 是否存在实例的原型链上

    console.log(p1 instanceof Object) // true
    // 因为Object.prototype可以被实例p1以原型链的方式访问到
1.2.4 构造函数存在的问题

构造函数在解决了上面所有问题,同时为实例带来了类型
但可以注意到在上例中,每个的实例的方法作用是一样的
但是每个实例被创建的时候都要重新声明一遍,浪费了内存

    // 我们再来看一下这个函数
    function People(name) {
        this.name = name
        this.sayName = function () {
            console.log(name)
        } // 每个实例的sayName方法却是相同的,而且每出现一个新实例,都是新声明一个函数,大大地浪费了内存
    }

能不能给People的实例都使用同一个sayName方法呢

1.3 构造函数&原型&原型链 1.3.1 构造函数

任何函数使用new表达式就是构造函数,也就是说这个函数成为了一个类

1.3.2 用原型链解决重复创建的问题

每个对象都会自带一个名称为prototype的属性

prototype属性是一个对象

    // 还是这个例子
    function People(name) {
        this.name = name
        this.sayName = function () {
            console.log(name)
        } 
    }
    var p1 = new People("sad")
    var p2 = new People("angry")
    
    // People本身就有prototype属性
    console.log(People.prototype) // {constructor: ƒ} 

    // 而每个对象也都会带有一个__proto__属性,指向这个构造函数【实例】的类
    // 所有的实例都共用一个prototype
    console.log(p1.__proto__ === People.prototype) // true
    console.log(p2.__proto__ === People.prototype) // true
    // 实例可以通过__prop__访问到其 类 的prototype属性,这就意味着类的prototype对象可以作为一个公共容器,供所有实例访问。
    People.prototype.test = "abc"
    console.log(p1.test) // abc

    // p1这个对象没有test属性,但是可以通过它的__proto__属性访问到People的prototype属性
上述关系我们用一张图来帮助大家更好地理解

1.3.3 解决内存浪费问题

由上我们可以知道

所有实例都会通过原型链引用到其类的prototype

prototype相当于所有实例都可以访问到的一个公共容器,这个公共容器也是这些实例的类的属性

那么如何解决内存浪费问题呢?

Answer:重复的东西移动到公共容器里就可以了

    function People(name) {
        this.name = name // 每个对象的name属性时不同的,这点无可厚非
    }

    People.prototype.sayName = function () {
        console.log(this.name)
    } // 将sayName方法放入People的原型中

    var p1 = new People("sad")
    var p2 = new People("angry")
    console.log(p1.sayName())
    console.log(p2.sayName())

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

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

相关文章

  • 深入浅出面向对象原型概念1】

    摘要:龚先生是一位在当地非常有名气的厨师,但他对自己用的锅一直不太满意,于是打算自己造一个龚先生想好了。 1.什么是面向对象 面向对象是一种思维方式[与语言无关],教你如何思考代码Object Oriented Programmingorient 的英文意思 是 使朝向那么,面向对象不如说成是以对象为目标的一种编程思维方式 2.面向对象的主要概念浅析 好了,现在让我们进入正题 面向对象的难点...

    djfml 评论0 收藏0
  • 深入浅出面向对象原型概念3】—— 原型继承

    摘要:由一个问题引发的思考这个方法是从哪儿蹦出来的首先我们要清楚数组也是对象,而且是对象的实例也就是说,下面两种形式是完全等价的只不过是一种字面量的写法,在深入浅出面向对象和原型概念篇文章里,我们提到过类会有一个属性,而这个类的实例可以通过属性访 1.由一个问题引发的思考 let arr1 = [1, 2, 3] let arr2 = [4, 5, 6] arr1.c...

    levinit 评论0 收藏0
  • 深入浅出面向对象原型【番外——重新认识new】

    摘要:前言我们在深入浅出面向对象和原型概念篇在这篇文章中了解到了如何使用解决重复创建浪费内存的问题,其中的关键就是,那么这篇文章让我们来重新了解的前世今生一个苦逼年级主任的故事开学啦高一年级主任龚主任需要为全年级每一位理科班新生录入学号并为每一位 前言 我们在深入浅出面向对象和原型【概念篇2】在这篇文章中了解到了如何使用new Function解决重复创建浪费内存的问题,其中的关键就是new...

    Apollo 评论0 收藏0
  • SegmentFault 技术周刊 Vol.32 - 七夕将至,你的“对象”还好吗?

    摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...

    李昌杰 评论0 收藏0
  • SegmentFault 技术周刊 Vol.32 - 七夕将至,你的“对象”还好吗?

    摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...

    Lyux 评论0 收藏0

发表评论

0条评论

DevTTL

|高级讲师

TA的文章

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