this的指向、工厂方法创建函数、构造函数

2023-05-16

一、this的指向(耐心看完,这个彻底理解,才不会成为一时的记忆)

1.我们先来看函数的参数:

  function fn(a,b ) {//形参
      console.log(a, b);//a:1,b:2
   }
  fn(1, 2)//实参

这没有问题的,其实函数的形参a,b就相当于声明了两个变量a,b,所以我们传入实参数值的时候就相当于给变量赋值,那么就能打印到a,b的值了

那么,函数fn,形参我传多余的参数,a,b,c,d,而实参呢,只有两个值,那么c,d打印的会是多少啊?

是undefined对不对啊,那么为什么呢,是因为声明了4个变量,只给前两个变量赋值,那么后两个变量声明了但没有赋值,我们是不是打印undefined

多说几句哈:

形参少传:就一个a, console.log(a, b);肯定b报错了啊,b没有声明,会报b没有被定义的错误

实参多传:那就打印a,b的值了,实参相当于赋值,连变量都没有,赋值给谁,打印谁啊,对吧

实参少传:实参就传一个值,其实实参少传不就是形参多传嘛,其实我们只去思考声明变量和赋值,就能知道打印结果了

2、什么是this?

this他就是一个参数,是一个函数内部隐含的参数,人家内部给你声明好的一个参数

function fn(a,b){
    console.log(a,b)//a:1,b:2
    console.log(this)//window
}
fn(1,2)

 指向:一个对象——函数执行的上下文对象

指向:根据函数调用方式的不同,指向不同

1.以fn()函数的形式调用,this永远指向window

function fn() {
    console.log(this);
}
fn()//Window

2.以obj.sayHi()方法的形式调用,this指向调用方法的那个对象,如obj

function fn() {
     console.log(this);
}       
let obj = {
    name: '张三',
    sayHi: fn
}
obj.sayHi() //this 就是 obj

 以方法的形式调用,哪个对象调用的这个方法,这个方法的this就是哪个对象
 

3、箭头函数的this

 箭头函数:没有自己的this 没有arguments、但是有剩余参数...arr

 使用场景:适合替代匿名函数

自己没有,找他的上一级

   // 箭头函数的this:自己没有,找他的上一级
        const fun = () => {
            console.log(this); //window
        }
        fun() //不是因为window.fun(),而是因为找父级作用域的this指向

对象方法的箭头函数this :

        // 对象方法的箭头函数this
        const obj = {
            name: 'h',
            sayHi: () => {
                console.log(this); //window,找的上一级的指向,找的就是window
            }
        }
        obj.sayHi()

        // 对象方法的箭头函数this
        const obj2 = {
            name: 'j',
            sayHi: function() {
                console.log(this); //this:obj2
                let i = 1
                const count = () => {
                    console.log(this); //this:obj2
                }
                count()
            }
        }
        obj2.sayHi()

DOM事件回调函数推荐不使用箭头函数,使用箭头函数,他就不指向DOM对象了,指向window

二、工厂方法创建函数

1、我们先创建几个对象:

 let obj = {
            name: '小新',
            age: 5,
            class: '向日葵小班',
            sayName: function() {
                alert(this.name);
            }
        }

let obj2 = {
            name: '风间',
            age: 5,
            class: '向日葵小班',
            sayName: function() {
                alert(this.name);
            }
        }


let obj3 = {
            name: '妮妮',
            age: 5,
            class: '向日葵小班',
            sayName: function() {
                alert(this.name);
            }
        }
obj2.sayName()

这样创建对象,重复性代码有点多,看起来较笨重,有没有利用重复性的代码呢

可以考虑写一个函数封装起来,然后调用一次是不是就生成了一个对象啊,就不用复制三分再去改了。

2.工厂方法创建函数

工厂方法创建函数就是一个函数,他能创建一个对象,理解工厂:批量的生产出来对象

function createPerson (name,age){
    //第一步:要new 一个对象
    let obj=new Object()
    //第二步:要给对象里添加点属性
    obj.name=name,
    obj.age=age
    obj.sayName=function() {
        alert(this.name)
    }
    //第三步:返回值
    return obj
}

//第四步:调用函数
let obj=createPerson("小新♥",5)
let obj2=createPerson("妮妮",5)
let obj3=createPerson("风间",5)
console.log(obj,obj2,obj3)

 这样就优雅的创建了三个对象,那么这里的this,指向哪里呢?

是不是以方法的形式调用的函数啊,那函数的this指向谁,obj3调用的就指向obj3了 ,所以函数sayName里的alert方法执行,this.name就是obj3对象里的name,就是风间了。

 三、构造函数

1.什么是构造函数?

就是一个普通的函数,不过调用的方式不同

普通函数调用:函数名()

构造函数调用:new 函数名()

另外,写法上,常首字符大写(规范,不是规定),最好首字母大写哈

    function Person(name, age) {
            this.name = name
            this.age = age 
            this.sayName = function() {
                alert(this.name)
            }
        }
        // 调用方式不同
        let p = new Person('风间', 5)
        let p2 = new Person('妮妮', 5)
        console.log(p, p2); //p 就是一个对象,只不过他有名字,名字就是那个函数的名字

我们先看函数,先忽略里面的this

 这回对象p,p2是不是有名字了啊

2.构造函数的this

        // 看this:那就要看构造函数的执行流程了

        // 1.你new 的方式调用了这个函数,那么(浏览器)就立即创建一个新的对象

        // 2.(浏览器)将新创建的对象设置为函数中的this

        // 3.逐行执行函数中的代码(代码咱们写的)

        // 4.(浏览器)将新建的对象作为函数返回值返回

总而言之:

this的指向:谁调用的函数,指向谁!!

以函数调用,是不是window.函数名()啊,谁调用的:window,指向谁:指向window

那么构造函数谁调用的:new 函数名(),指向谁:new 函数名(),他把他赋值给变量p,那么变量p,就是new 函数名(),那么p就是对象,this就指向p

3.类、类的实例对象

这计算机概念性名字听起来挺难理解哈,别怕,他就是个名字,我们来理解他

使用同一个构造函数创建的对象,我们称为一类对象( p,p2是一个类的,d,d2是一个类的

也将这个构造函数称为一个类(如:构造函数Person称为类,构造函数Dog称为类,这就是两个类)

将通过一个构造函数创建的对象,称为是该类的实例

谁是通过构造函数创建的对象:p p2 d d2  ,这玩意叫实例,p p2 d d2叫实例

(如:p,p2,d,d2是实例,p,p2是Person类的实例,d,d2是Dog类的实例)

补充:

   // instanceof 检查一个对象是否是一个类的实例
        console.log(p instanceof Person); //true
        console.log(d instanceof Person); //false

        // Object 是所有对象的祖先
        // 任何对象 instanceof Object 都会是true
        console.log(p instanceof Object); //true
        console.log(d instanceof Object); //true

4.问题

 // 问题:什么叫类?这个构造函数称为一个类

 // 什么叫实例?实例就是一个对象,构造函数干嘛的?创建对象的,通过构造函数创建出来的对象

 // 什么叫构造函数?new 出来的一个函数

// 构造函数与普通函数的区别?调用方式不同

//构造函数的this指向? 谁调用的指向谁,构造函数的this指向他的实例对象。

5.补充

在构造函数内部创建了一个方法sayName,每个实例对象p1,p2,p3就都有了自己独立的方法,那么创建1000个实例对象,就会有1000个方法,这1000个方法都一摸一样,完全为了实现一个功能,这样太消耗内存了

 // 构造函数
        function Person(name, age) {
            this.name = name
            this.age = age
            this.sayName = function() {
                alert(this.name)
            }
        }
        let p1 = new Person('小新', 5)
        let p2 = new Person('妮妮', 5)
        let p3 = new Person('风间', 5)
            // p1.sayName()
            // p2.sayName()
            // p3.sayName()
        console.log(typeof p1.sayName); //function
        console.log(p1.sayName == p2.sayName); //false

把函数放到全局上,他就只有这么一个函数,提升性能,创建1000个实例对象,还是这一个方法

        function Person(name, age) {
            this.name = name
            this.age = age
            this.sayName = fn
        }
        let p1 = new Person('小新', 5)
        let p2 = new Person('妮妮', 5)
        let p3 = new Person('风间', 5)


        function fn() {
            alert(this.name)
        }

        console.log(p1.sayName == p2.sayName); //true

但是这样写是有问题的,污染了全局作用域的命名空间,别人在写个函数叫fn,就会覆盖你的fn了,所以我们把他写在原型上

function Person(name, age) {
            this.name = name
            this.age = age
            // this.sayName = fn
        }
        let p1 = new Person('小新', 5)
        let p2 = new Person('妮妮', 5)
        let p3 = new Person('风间', 5)

Person.prototype.sayName = function() {
            alert(this.name)
}

p1.sayName()
console.log(p1.sayName == p2.sayName); //true

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

this的指向、工厂方法创建函数、构造函数 的相关文章

随机推荐

  • Java面试题

    Java面试题 并发面试题 集合面试题 一 Java基础 1 JDK和JRE有什么区别 JDK xff1a Java Development Kit 的简称 xff0c java 开发工具包 xff0c 提供了 java 的开发环境和运行环
  • VM虚拟机使用(文末有系统镜像)

    目录 前言 1 创建虚拟机 2 分盘操作 3 安装系统 4 备份 前言 本篇文章笔者详细述说了虚拟机的使用 xff0c 安装的是xp系统 xff0c 文末链接里面有xp与win7的系统镜像 若有问题 xff0c 希望大家斧正 xff08 手
  • linux必知必会-du命令

    du命令 du命令简介 du命令是linux系统里的文件大小查看的命令 du命令的应用场景十分广泛 xff1a 需要查看单个目录里面多个文件总大小 需要查看目录中每个文件的大小以及每个子文件夹中文件的大小 查看日志文件的大小 查看文件大小并
  • 解决在Ubuntu中设置了共享文件却找不到的原因

    可以看到我们在进入共享文件夹的时候 xff0c 并没有找到我们想要的文件 但文件夹里面是实实在在有文件的 解决方法 sudo vmhgfs fuse host mnt hgfs o nonempty o allow other 这个解决方法
  • python斐波那契数列

    基础python题 斐波那契数列 斐波那契数列指的是这样一个数列 xff1a 0 xff0c 1 1 xff0c 2 3 xff0c 5 8 xff0c 13 21 34 55 89 144 233 377 610 987 1597 题目分
  • python经典猴子偷桃

    猴子偷桃 题目 猴子吃桃问题 xff1a 猴子第一天摘下若干个桃子 xff0c 当即吃了一半 xff0c 还不瘾 xff0c 又多吃了一个第二天早上又将剩下的桃子吃掉一半 xff0c 又多吃了一个 以后每天早上都吃了前一天剩下的一半零一个
  • python分解质因数

    分解质因数 题目 题目 将一个整数分解质因数 例如 xff1a 输入90 打印出90 61 233 5 程序分析 根本不需要判断是否是质数 xff0c 从2开始向数本身遍历 xff0c 能整除的肯定是最小的质数 代码如下 target sp
  • C语言学习笔记——数组

    数组 eg xff1a 使用数组保存数据 使用数组保存用户输入的数据 当输入完毕后逆向输出数据 span class token macro property span class token directive keyword inclu
  • c语言基础——一维数组的应用

    C语言基础 一维数组的应用 例如 在一个学校的班级中会有很多学生 此时就可以使用数组来保存这些学生的姓名 以便进行管理 eg xff1a 用数组保存学生姓名 本示例每一个元素都应该是可以保存字符串的类型 这里使用字符指针类型 span cl
  • c-起泡法

    起泡法 这个算法的名字由来是因为越小的元素会经由交换慢慢 浮 到数列的顶端 xff08 升序或降序排列 xff09 xff0c 就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样 xff0c 故名 冒泡排序 比较相邻的元素 如果第一个比第二
  • c++字符串连接

    编写一个程序 xff0c 将两个字符串连接起来 xff0c 结果取代第一个字符串 要求用string方法 int main int a b cin gt gt a gt gt b sort a b cout lt lt a lt lt 34
  • 用new调用函数的四步走

    JS规定 xff0c 使用new调用函数会进行四步走 xff1a 1 函数体内会自动创建出一个空白对象 2 函数的上下文 xff08 this xff09 会自动指向这个对象 3 函数体内的语句会执行 4 函数会自动返回上下文对象 xff0
  • P1786 帮贡排序

    题目背景 在absi2011的帮派里 xff0c 死号偏多 现在absi2011和帮主等人联合决定 xff0c 要清除一些死号 xff0c 加进一些新号 xff0c 同时还要鼓励帮贡多的人 xff0c 对帮派进行一番休整 题目描述 目前帮派
  • vim如何提高效率:使用jk绑定Esc

    vim使用jk绑定Esc 为什么要使用jk绑定Esc vim的精华就在于几个基本的模式插入模式 底行模式 可视模式 xff0c 命令模式 正是因为这几个模式的存在让vim效率极高 虽然如此 xff0c 经常使用vim的人不难体会到从插入模式
  • Docker 安装mysql 解决中文乱码,数据持久化进入本地

    目录 一 xff1a 简单版的 xff08 没有持久化 xff0c 有乱码 xff0c 直接run 的容器实例 xff09 1 拉取镜像到本地 2 安装运行简单版 2 1 验证使用 xff0c 建库建表插入数据 2 2外部Win10也来连接
  • python中while语句

    一 while语句 1语法 xff1a while 条件 条件成立重复执行的代码1 条件成立重复执行的代码2 运用while语句需要注意 xff1a 1 初始值 2 跳出while的条件 3 计数器的变化 xff08 自增自减等等 xff0
  • SPSS数据分析

    第一题 表1 居民健康状况调查情况 编号 身高 xff08 cm xff09 体重 xff08 kg xff09 代谢综合征 性别 胆固醇 xff08 mmol L xff09 1 173 0 87 5 0 0 4 17 2 168 0 7
  • HA高可用集群文档搭建

    HA高可用集群文档搭建 准备工作 1 准备好三台虚拟机分别为hadoop01 hadoop02 hadoop03 创建安装包以及安装后的文档文件夹 span class token punctuation span root 64 hado
  • Python 计算机视觉(十三)—— 图像的傅里叶变换

    参考的一些文章以及论文我都会给大家分享出来 链接就贴在原文 xff0c 论文我上传到资源中去 xff0c 大家可以免费下载学习 xff0c 如果当天资源区找不到论文 xff0c 那就等等 xff0c 可能正在审核 xff0c 审核完后就可以
  • this的指向、工厂方法创建函数、构造函数

    一 this的指向 耐心看完 xff0c 这个彻底理解 xff0c 才不会成为一时的记忆 1 我们先来看函数的参数 xff1a function fn a b 形参 console log a b a 1 b 2 fn 1 2 实参 这没有