JavaScript 函数调用和JavaScript 闭包

news2024/11/18 20:31:24

文章目录

  • 一、JavaScript 函数调用
  • 二、JavaScript 闭包
  • 总结

一、JavaScript 函数调用

JavaScript 函数有 4 种调用方式。

每种方式的不同在于 this 的初始化。

  • this 关键字

一般而言,在Javascript中,this指向函数执行时的当前对象

注意 this 是保留关键字,你不能修改 this 的值。

  • 调用 JavaScript 函数

函数中的代码在函数被调用后执行。

  • 作为一个函数调用
function myFunction(a, b) {
    return a * b;
}
myFunction(10, 2);           // myFunction(10, 2) 返回 20

在 HTML 中默认的全局对象是 HTML 页面本身,所以函数是属于 HTML 页面。

在浏览器中的页面对象是浏览器窗口(window 对象)。以上函数会自动变为 window 对象的函数。

myFunction() 和 window.myFunction() 是一样的:

function myFunction(a, b) {
    return a * b;
}
window.myFunction(10, 2);    // window.myFunction(10, 2) 返回 20
  • 全局对象

当函数没有被自身的对象调用时 this 的值就会变成全局对象

在 web 浏览器中全局对象是浏览器窗口(window 对象)。

该实例返回 this 的值是 window 对象:

function myFunction() {
    return this;
}
myFunction();                // 返回 window 对象

函数作为全局对象调用,会使 this 的值成为全局对象。
使用 window 对象作为一个变量容易造成程序崩溃。

  • 函数作为方法调用

在 JavaScript 中你可以将函数定义为对象的方法。

以下实例创建了一个对象 (myObject), 对象有两个属性 (firstName 和 lastName), 及一个方法 (fullName):

var myObject = {
    firstName:"John",
    lastName: "Doe",
    fullName: function () {
        return this.firstName + " " + this.lastName;
    }
}
myObject.fullName();         // 返回 "John Doe"

fullName 方法是一个函数。函数属于对象myObject 是函数的所有者。

this对象,拥有 JavaScript 代码。实例中 this 的值为 myObject 对象

测试以下!修改 fullName 方法并返回 this 值:

var myObject = {
    firstName:"John",
    lastName: "Doe",
    fullName: function () {
        return this;
    }
}
myObject.fullName();          // 返回 [object Object] (所有者对象)

函数作为对象方法调用,会使得 this 的值成为对象本身。

  • 使用构造函数调用函数

如果函数调用前使用了 new 关键字, 则是调用了构造函数

这看起来就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象

// 构造函数:
function myFunction(arg1, arg2) {
    this.firstName = arg1;
    this.lastName  = arg2;
}
 
// This    creates a new object
var x = new myFunction("John","Doe");
x.firstName;                             // 返回 "John"

构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法。 构造函数中 this 关键字没有任何的值。
this 的值在函数调用实例化对象(new object)时创建。

  • 作为函数方法调用函数

在 JavaScript 中, 函数是对象。JavaScript 函数有它的属性和方法

call() 和 apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身

function myFunction(a, b) {
    return a * b;
}
myObject = myFunction.call(myObject, 10, 2);     // 返回 20
function myFunction(a, b) {
    return a * b;
}
myArray = [10, 2];
myObject = myFunction.apply(myObject, myArray);  // 返回 20

两个方法都使用了对象本身作为第一个参数。 两者的区别在于第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)

在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。

在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。

通过 call() 或 apply() 方法你可以设置 this 的值, 且作为已存在对象的新方法调用。

二、JavaScript 闭包

JavaScript 变量可以是局部变量或全局变量。

私有变量可以用到闭包。

  • 全局变量

函数可以访问由函数内部定义的变量,如:


function myFunction() {
    var a = 4;
    return a * a;
}

函数也可以访问函数外部定义的变量,如:


var a = 4;
function myFunction() {
    return a * a;
}

后面一个实例中, a 是一个 全局 变量。

在web页面中全局变量属于 window 对象。

全局变量可应用于页面上的所有脚本。

在第一个实例中, a 是一个 局部 变量。

局部变量只能用于定义它函数内部。对于其他的函数或脚本代码是不可用的。

全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。 

变量声明时如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义

  • 变量生命周期

全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。

而在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。

  • 计数器困境

设想下如果你想统计一些数值,且该计数器在所有函数中都是可用的。

你可以使用全局变量,函数设置计数器递增:

var counter = 0;
 
function add() {
   return counter += 1;
}
 
add();
add();
add();
 
// 计数器现在为 3

在这里插入图片描述
计数器数值在执行 add() 函数时发生变化。

但问题来了,页面上的任何脚本都能改变计数器,即便没有调用 add() 函数。

如果我在函数内声明计数器,如果没有调用函数将无法修改计数器的值

function add() {
    var counter = 0;
    return counter += 1;
}
 
add();
add();
add();
 
// 本意是想输出 3, 但事与愿违,输出的都是 1 !

在这里插入图片描述

  • JavaScript 内嵌函数

所有函数都能访问全局变量。

实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。
JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量

该实例中,内嵌函数 plus() 可以访问父函数的 counter 变量


function add() {
    var counter = 0;
    function plus() {counter += 1;}
    plus();    
    return counter; 
}

如果我们能在外部访问 plus() 函数,这样就能解决计数器的困境。

我们同样需要确保 counter = 0 只执行一次。

我们需要闭包。

  • JavaScript 闭包

还记得函数自我调用吗?该函数会做什么?

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();
 
add();
add();
add();
 
// 计数器为 3
实例解析

变量 add 指定了函数自我调用的返回字值。

自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。

add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。

这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。

计数器受匿名函数的作用域保护,只能通过 add 方法修改。

闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。
直观的说就是形成一个不销毁的栈环境。

学习来自“https://www.runoob.com/js”

总结

尝试着每天锻炼自己的思维方式,这样才能成为一个真正的领域专家。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/455217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

美创科技首届渠道高峰论坛| 两大分论坛亮点汇聚

4月22日,美创科技首届渠道高峰论坛在海南三亚隆重举行,本届高峰论坛以“新起点 新战略 共赢数安蓝海”为主题,全国各地200余家合作伙伴齐聚。当日下午,行业分论坛、技术分论坛两大论坛以及圆桌会议,多方视角、全方位共…

C++篇----auto、内联函数、函数重载

文章目录 一、auto二、内联函数&#xff08;inline)三、函数重载 一、auto auto在c中是会根据等号右边表达式自动推导等号左边的类型 #include<iostream> using namespace std;int main() {int a 0;auto b a;double c 1.1;auto d c;//打印类型typeid().name()cout &l…

OpenGL与Metal API的Point Sprite

我们在实际用OpenGL等3D图形渲染API时 点图元 往往用得不多&#xff0c;而在粒子系统中可能也是用一个正方形来绘制一单个粒子。不过在当前大部分3D图形渲染API中都能支持用点图元来绘制一个具有纹理贴图的粒子&#xff0c;从早在OpenGL 1.4开始就能支持了&#xff0c;而在Open…

机器学习:基于逻辑回归(Logistic Regression)对股票客户流失预测分析

基于逻辑回归对股票客户流失预测分析 作者&#xff1a;i阿极 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏&#x1f4c1…

npm install报错

出现这个错误&#xff0c;我百度之后得到的解决方案是&#xff1a; 在node.js安装目录下找到node_modules文件夹并删除 但是当我操作完成之后&#xff0c;却出现了另外一个ERROR&#xff1a; 于是我又还原了原来的node_modules文件夹&#xff0c;于是又报一开始的错 仔细瞅瞅…

Netty 单机百万连接测试

1.Netty框架简介 1.1.Netty简介 netty是jboss提供的一个java开源框架&#xff0c;netty提供异步的、事件驱动的网络应用程序框架和工具&#xff0c;用以快速开发高性能、高可用性的网络服务器和客户端程序。也就是说netty是一个基于nio的编程框架&#xff0c;使用netty可以快…

NFC 学习笔记 5 MFRC522读写器2 NDEF

NDEF简介 NDEF&#xff08;NFC Data Exchange Format&#xff09;是一种标准化的数据格式&#xff0c;用于将数据存储在NFC标签或智能手机中。该格式是NFC论坛定义的&#xff0c;目的是在不同的NFC设备之间交换信息。 NDEF格式可以存储各种类型的数据&#xff0c;例如URL、文本…

面对市场内卷,不同品牌应该如何做客户增长?

后疫情时代&#xff0c;我国新生人口减少、人口老龄化加剧&#xff0c;chatgpt火爆和AI替代论盛行&#xff0c;市场上&#xff0c;口红效应依旧繁荣&#xff0c;消费者的延迟满足、替代性满足成为常见心理&#xff0c;面对宏观的不确定性&#xff0c;人们在消费上更需要确定性的…

github 基础

github 基础 前面讲了 git 的基本使用&#xff0c;这里简单的提一下 github 的基本使用&#xff0c;主要还是 pull 和 push 两个部分。其中 pull 好像有了一些变化&#xff0c;现在似乎是需要 rebase 而不是自动就帮你做了……&#xff1f;不过 rebase 的部分之后再提。 当然…

Vuex实现数据共享

目录 一&#xff1a;index.js的创建 二&#xff1a;index.js的引入 三&#xff1a;Count.vue 四&#xff1a;App.vue的使用 五&#xff1a;mapstate等的使用 五&#xff1a;多组件数据共享&#xff08;模块化编程&#xff09; vc通过dispatch联系actions&#xff0c;acti…

Python小姿势 - ###### 随机选取的知识点:Python日期时间处理

随机选取的知识点&#xff1a;Python日期时间处理 Python日期时间处理&#xff1a;一种更简单的方式 日期和时间处理是许多程序中必不可少的部分。Python提供了一个标准库来处理日期和时间&#xff0c;这个库叫做datetime&#xff0c;它提供了一些类来处理不同的日期和时间格式…

远程访问及控制(SSH)

远程访问及控制&#xff08;SSH&#xff09; 一、SSH远程管理二、SSH服务1、ssh远程登录方式2、scp远程复制3、sftp安全FTP4、sshd配置文件5、ssh密钥对配置5.1 ssh密钥对免交互登录 三、TCP wrappers 访问控制1、**TCP wrappers &#xff08;TCP封套&#xff09;**2、**TCP wr…

会话与会话技术(Cookie)

Web应用中的会话过程指的是一个客户端&#xff08;浏览器&#xff09;与Web服务器之间连续发生的一系列请求和响应过程 为保存会话过程产生的数据&#xff0c;Servlet提供了两个用于保存会话数据的对象&#xff0c;分别是Cookie和Session 1、Cookie对象 Cookie是一种会话技术…

SS524V100 RTL8152B(USB转网卡)驱动移植

目录 前言 1. 内核下 USB Host 配置过程 2. 内核下 RTL8152 驱动配置 3. 重新编译内核 4. 测试USB转网卡 5. 总结 前言 本文主要是描述 SS524V100 对 RTL8152B(百兆网卡) 开发、移植的过程。 1. SS524V100 的 USB 2.0 支持 Host 模式&#xff1b; 2. 内核默认自带驱动…

0环境教你怎么安装配置GPU环境运行车流量检测代码

项目效果&#xff1a; python车流量检测双向车流计数 1、环境配置 1.1 安装显卡加速工具 (1) 安装CUDA和cudnn NVIDIA CUDA 深度神经网络库 (cuDNN) 是经 GPU 加速的深度神经网络基元库。cuDNN 可大幅优化标准例程&#xff08;例如用于前向传播和反向传播的卷积层、池化层、…

4月23日作业

#include <iostream> #include <cstring> using namespace std; class Student //学生类 { private: string name; //姓名 int year; //年龄 double sorce; //分数 public: Student (){} //无参构造 Student(string a,int b,double c):name(a),y…

五分钟学会在微信小程序中使用 vantUI 组件库

前言 我们在开发微信小程序时&#xff0c;设计和实现好用的用户界面无疑是至关重要的一步。但是微信小程序官方自带的 UI 组件库无法满足很多使用场景&#xff0c;这个时候就需要我们使用一些第三方的 UI 组件库。而 vant Weapp 作为一款优秀的前端 UI 组件库&#xff0c;可以帮…

MP长篇综述 | 植物泛基因组及其应用

2022年12月15日&#xff0c;中山大学史俊鹏副教授、中国科学院遗传与发育生物学研究所田志喜研究员、中国农业大学赖锦盛教授和上海师范大学黄学辉教授共同撰文&#xff0c;在Molecular Plant杂志发表了题为“Plant pan-genomics and its applications”的长篇综述。该论文对植…

(Ubuntu22.04 Jammy)安装ROS2 Humble

文章目录 (Ubuntu22.04 Jammy)安装ROS2 (Humble)版本一、设置本地区域二、设置源三、安装ROS2软件包四、环境设置五、测试用例Talker-listener 六、卸载ros2 (Ubuntu22.04 Jammy)安装ROS2 (Humble)版本 提示&#xff1a;以下内容是已经安装了ubuntu22.04 下进行安装ros2 一、设…

iptables防火墙和Firewalld

引言 在 Internet 中&#xff0c;企业通过各种应用系统来为用户提供各种服务&#xff0c;如 Web 网站、电子邮件系统、FTP 服务器、数据库系统等&#xff0c;那么&#xff0c;如何来保护这些服务器&#xff0c;过滤企业不需要的访问甚至是恶意的入侵呢&#xff0c;接下来&#…