Android音视频: 引入FFmpeg

本文你可以了解到

本文将介绍如何将上一篇文章编译出来的  FFmpeg so 库,引入到  Android 工程中,并验证  so 是否可以正常使用。

一、开启 Android 原生 C/C++ 支持

在过去,通常使用 makefile 的方式在项目中引入 C/C++ 代码支持,随着 Android Studio 的普及,makefile 的方式已经基本被 CMake 替代。

有了 Android 官方的支持,NDK 层代码的开发变得更加容易。以前一谈到 Android NDK ,许多人就会大惊失色,感觉是深不可测的东西,一方面是 makefile 的编写很难,一方面是 C/C++ 相比 Java 来说,比较晦涩。

但是不必担心,一是有了 CMake ,二是对于 C/C++ 的基本使用其实和 Java 差不多,本系列涉及到的,也都是对 C/C++ 的基础使用,毕竟,高级的我也不会不是吗?哈哈哈~~

1. 安装 CMake

首先,需要下载 CMake 相关工具,在 Android Studio 中依次点击 Tools->SDK Manager->SDK Tools,然后勾选

CMake : CMake 构建工具

LLDB : C/C++ 代码调试工具

NDK : NDK 环境

最后依次点击 OK->OK->Finish ,开始下载(文件比较大,可能会比较慢,请耐心等待)。

下载CMake工具

2. 添加 C/C++ 支持

有两种方式:

一是,新建一个新的工程,并勾选  C/C++ 支持选项,系统将自动创建一个支持  C/C++ 编码的工程。
二是,在已有的项目上,手动添加所有的添加项来支持  C/C++ 编码,其实就是自己手动添加 「第一种方式」中  Android Studio 为我们自动创建的那些东西。

首先,通过新建一个新工程的方式,看看 IDE 为我们生成了那些东西。

1)新建 C/C++ 工程

依次点击 File -> New -> New Project,进入新建工程页面,拉到最后,选择 Native C++ 然后按照默认配置,一路 Next -> Next -> Finish 即可。

新建C++工程

2)Android Studio 自动生成了什么

生成的工程目录如下:

工程目录

重点关注上图标注的3个地方:

  • 第一,最上层的 MainActivity
  class MainActivity : AppCompatActivity() {
​override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)
​// Example of a call to a native methodsample_text.text = stringFromJNI()}
​/*** A native method that is implemented by the 'native-lib' native library,* which is packaged with this application.*/external fun stringFromJNI(): String
​companion object {
​// Used to load the 'native-lib' library on application startup.init {System.loadLibrary("native-lib")}}}

很简单,使用过 so 库的应该都看得懂,这里简单说一下。

代码的最下面,companion object 在 Kotlin 中表示静态代码块,类似 Java 中的 static { },其中的代码有且只会被执行一次。

接着在 init{} 方法中,加载了 C/C++ 代码编译成的 so 库: native-lib

往上一句代码,用 external 声明了一个外部引用的方法 stringFromJNI() ,这个方法和 C/C++ 层的代码是对应的。

最终在最上面的 onCreate 中,将从 C/C++ 层返回的 String 显示出来。

【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~

  • 第二,创建了一个 cpp 文件包

其中有两个文件非常重要,分别是 native-lib.cpp 、 CMakeLists.txt

i. native-lib.cpp :是一个 C++ 接口文件,在 MainActivity 中声明的外部方法将在这里得到实现。

自动生成 native-lib.cpp 的内容如下:

  #include <jni.h>#include <string>
​extern "C" JNIEXPORT jstring JNICALLJava_com_chenlittleping_mynativeapp_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());}

可以看到,这个 cpp 文件中的方法命名非常的长,不过其实非常简单。

首先是头部固定写法 extern "C" JNIEXPORT jstring JNICALL

extern "C" 表示以 C语言 的方式来编译;

jstring 表示该方法返回类型是 Java 层的 String 类型,类似的还是有: void jint等;

然后是 Java 层对应方法的映射,即整个方法命名其实是 Java 层对应方法的绝对路径。

其中,最前面的 Java_ 是固定写法;

com_chenlittleping_mynativeapp_MainActivity_: 对应的是 com.chenlittleping.mynativeapp.MainActivity.,其实就是 . 换为 _

stringFromJNI 和 Java 层的方法一致。

最后是两个参数, JNIEnv *env 和 jobject,分别代表 JNI 的上下文环境和调用这个接口的 Java 的类的实例。

调用这个方法,将会在 C++ 层创建一个字符串,并以 Java#String 的类型返回。

ii. CMakeLists.txt : 也就是构建脚本。内容如下:

  # cmake 最低版本cmake_minimum_required(VERSION 3.4.1)
​# 配置so库编译信息add_library( # 输出so库的名称native-lib
​# 设置生成库的方式,默认为SHARE动态库SHARED
​# 列出参与编译的所有源文件native-lib.cpp)
​# 查找代码中使用到的系统库find_library( # Sets the name of the path variable.log-lib
​# Specifies the name of the NDK library that# you want CMake to locate.log)
​# 指定编译目标库时,cmake要链接的库target_link_libraries(# 指定目标库,native-lib 是在上面 add_library 中配置的目标库native-lib# 列出所有需要链接的库${log-lib})

这是最简单的编译配置,具体见上面的注释。

CMakeLists.txt 的目的就是配置可以编译出 native-lib so 库的构建信息。

说白了,就是告诉编译器:

  - 编译的目标是谁- 依赖的源文件在哪里找- 依赖的 `系统或第三方` 的 `动态或静态` 库在哪里找。
  • 第三,在 Gradle 文件中注册 CMake 脚本

在 第二步 中,已经把构建 so 库的信息配置好了,接下来要把这些信息注册到 Gradle 中,编译器才会去编译它。

app 的 build.gradle 内容如下:

  apply plugin: 'com.android.application'
​apply plugin: 'kotlin-android'apply plugin: 'kotlin-android-extensions'
​android {compileSdkVersion 28buildToolsVersion "29.0.1"defaultConfig {applicationId "com.chenlittleping.mynativeapp"minSdkVersion 19targetSdkVersion 28versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"// 1) CMake 编译配置externalNativeBuild {cmake {cppFlags ""}}}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}// 2) 配置 CMakeLists 路径externalNativeBuild {cmake {path "src/main/cpp/CMakeLists.txt"version "3.10.2"}}}
​dependencies {// 省略无关代码//......}

最主要的两个地方是两个 externalNativeBuild 。

第 1 个 externalNativeBuild 中,可以做一些优化配置,比如只打包包含 armeabi 架构的 so :

  externalNativeBuild {cmake {cppFlags ""}ndk {abiFilters  "armeabi" //, "armeabi-v7a"}}

第 2 个 externalNativeBuild,主要是配置 CMakeLists.txt 的路径和版本。

Android Studio 为我们生成的关于  C/C++ 支持的主要就是以上三个地方,有了以上配置,就可以在  MainActivity 页面中正常的显示出  Hello from C++ 。

3) 在已有工程上添加 C/C++ 支持

前面就说过,在已有项目上添加 C/C++ 支持,就是由我们自己手动添加整个配置。那么根据签名介绍的三个步骤,依葫芦画瓢,就可以添加了。

这里刚好就用添加 FFMpeg so 到本系列文章现有 Demo 工程中来演示一遍。

二、引入 FFmpeg so

1. 新建 cpp 目录

首先,在 app/src/main/ 目录下,新建文件夹,并命名为 cpp 。

接着,在 cpp 目录下,右键 New -> C/C++ Source File ,新建 native-lib.cpp 文件。

接着,在 cpp 目录下,右键 New -> File ,新建 CMakeLists.txt ,先将上面 IDE 生成的那份代码粘贴进来, FFmpeg的配置在后面详细讲解。

  # CMakeLists.txt
​# cmake 最低版本cmake_minimum_required(VERSION 3.4.1)
​# 配置so库编译信息add_library( # 输出so库的名称native-lib
​# 设置生成库的方式,默认为SHARE动态库SHARED
​# 列出参与编译的所有源文件native-lib.cpp)
​# 查找代码中使用到的系统库find_library( # Sets the name of the path variable.log-lib
​# Specifies the name of the NDK library that# you want CMake to locate.log)
​
# 指定编译目标库时,cmake要链接的库
target_link_libraries(# 指定目标库,native-lib 是在上面 add_library 中配置的目标库native-lib
​# 列出所有需要链接的库${log-lib})

2. 将 CMakeLists 配置到 build.gradle 中

  android {// ...defaultConfig {// ...// 1) CMake 编译配置externalNativeBuild {cmake {cppFlags ""}}}// ...// 2) 配置 CMakeLists 路径externalNativeBuild {cmake {path "src/main/cpp/CMakeLists.txt"version "3.10.2"}}}
​// ...

如果只是简单的编写 C/C++ 代码,以上基础配置就可以了。

接着来看看本文的重点,如何使用 CMakeLists.txt 引入 FFmpeg 的动态库。

3. 将 FFmpeg so 库放到对应的 CPU 架构目录

在 上一篇文章中,我们编译的 FFmpeg so 库的 CPU 架构为 armv7-a,所以,我们需要把所有的 so 库放置到 armeabi-v7a 目录下。

首先,在 app/src/main/ 目录下,新建文件夹,并命名为 jniLibs 。

app/src/main/jniLibs 是 Android Studio 默认的放置 so 动态库的目录。

接着,在 jniLibs 目录下,新建 armeabi-v7a 目录。

最后把 FFmpeg 编译得到的所有 so 库粘贴到 armeabi-v7a 目录。如下:

so目录

4. 添加 FFmpeg so 的头文件

在编译 FFmpeg 的时候,除了生成 so 外,还会生成对应的 .h 头文件,也就是 FFmpeg 对外暴露的所有接口。

FFmpeg编译输出

在 cpp 目录下,新建 ffmpeg 目录,然后把编译时生成的 include 文件粘贴进来。

头文件目录

5. 添加、链接 FFmpeg so 库

上面已经把 so 和 头文件 放置到对应的目录中了,但是编译器是不会把它们编译、链接、并打包到 Apk 中的,我们还需要在 CMakeLists.txt 中显性的把相关的 so 添加和链接起来。完整的 CMakeLists.txt 如下:

  cmake_minimum_required(VERSION 3.4.1)
​# 支持gnu++11set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
​# 1. 定义so库和头文件所在目录,方面后面使用set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/ffmpeg)
​# 2. 添加头文件目录include_directories(${ffmpeg_head_dir}/include)
​# 3. 添加ffmpeg相关的so库add_library( avutilSHAREDIMPORTED )set_target_properties( avutilPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavutil.so )
​add_library( swresampleSHAREDIMPORTED )set_target_properties( swresamplePROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libswresample.so )add_library( avcodecSHAREDIMPORTED )set_target_properties( avcodecPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavcodec.so )add_library( avfilterSHAREDIMPORTED)set_target_properties( avfilterPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavfilter.so )add_library( swscaleSHAREDIMPORTED)set_target_properties( swscalePROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libswscale.so )
​add_library( avformatSHAREDIMPORTED)set_target_properties( avformatPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavformat.so )
​add_library( avdeviceSHAREDIMPORTED)set_target_properties( avdevicePROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavdevice.so )
​# 查找代码中使用到的系统库find_library( # Sets the name of the path variable.log-lib
​# Specifies the name of the NDK library that# you want CMake to locate.log )
​# 配置目标so库编译信息add_library( # Sets the name of the library.native-lib
​# Sets the library as a shared library.SHARED
​# Provides a relative path to your source file(s).native-lib.cpp)
​# 指定编译目标库时,cmake要链接的库        target_link_libraries( 
​# 指定目标库,native-lib 是在上面 add_library 中配置的目标库native-lib
​# 4. 连接 FFmpeg 相关的库avutilswresampleavcodecavfilterswscaleavformatavdevice
​# Links the target library to the log library# included in the NDK.${log-lib} )

主要看看注释中新加入的 1~4 点。

1)通过 set 方法定义了 so 和 头文件 所在目录,方便后面使用。

其中  CMAKE_SOURCE_DIR 为系统变量,指向  CMakeLists.txt 所在目录。  ANDROID_ABI 也是系统变量,指向 so 对应的  CPU 框架目录:armeabi、armeabi-v7a、x86 ...
set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/ffmpeg)

2)通过 include_directories 设置头文件查找目录

include_directories(${ffmpeg_head_dir}/include)

3)通过 add_library 添加 FFmpeg 相关的 so 库,以及 set_target_properties 设置 so 对应的目录。

其中,add_library 第一个参数为 so 名字, SHARED 表示引入方式为动态库引入。
  add_library( avcodecSHAREDIMPORTED )set_target_properties( avcodecPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavcodec.so )

4)最后,通过 target_link_libraries 把前面添加进来的 FFMpeg so 库都链接到目标库 native-lib 上。

这样,我们就将 FFMpeg 相关的 so 库都引入到当前工程中了。下面就要来测试一下,是否可以正常调用到 FFmpeg 相关的方法了。

三、使用 FFmpeg

要检查 FFmpeg 是否可以使用,可以通过获取 FFmpeg 基础信息来验证。

1. 在 FFmpegAcrtivity 中添加一个外部方法 ffmpegInfo

把获取到的 FFmpeg 信息显示出来。

  class FFmpegActivity: AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_ffmpeg_info)
​tv.text = ffmpegInfo()}
​private external fun ffmpegInfo(): String
​companion object {init {System.loadLibrary("native-lib")}}}

2. 在 native-lib.cpp 中添加对应的 JNI 层方法

  #include <jni.h>#include <string>#include <unistd.h>extern "C" {#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libavfilter/avfilter.h>#include <libavcodec/jni.h>
​JNIEXPORT jstring JNICALLJava_com_cxp_learningvideo_FFmpegActivity_ffmpegInfo(JNIEnv *env, jobject  /* this */) {
​char info[40000] = {0};AVCodec *c_temp = av_codec_next(NULL);while (c_temp != NULL) {if (c_temp->decode != NULL) {sprintf(info, "%sdecode:", info);switch (c_temp->type) {case AVMEDIA_TYPE_VIDEO:sprintf(info, "%s(video):", info);break;case AVMEDIA_TYPE_AUDIO:sprintf(info, "%s(audio):", info);break;default:sprintf(info, "%s(other):", info);break;}sprintf(info, "%s[%10s]\n", info, c_temp->name);} else {sprintf(info, "%sencode:", info);}c_temp = c_temp->next;}return env->NewStringUTF(info);}}

首先,我们看到代码被包裹在 extern "C" { } 当中,和前面的系统创建的稍微有些不同,通过这个大括号包裹,我们就不需要每个方法都添加单独的 extern "C" 开头了。

另外,由于 FFmpeg 是使用 C 语言编写的,所在 C++ 文件中引用 #include 的时候,也需要包裹在 extern "C" { },才能正确的编译。

方法的新建就不用说了,和前面介绍的命名方法一致。

在方法中,使用 FFmpeg 提供的方法 av_codec_next,获取到 FFmpeg 的编解码器,然后通过循环遍历,将所有的音视频编解码器信息拼接起来,最后返回给 Java 层。

至此,FFmpeg 加入到工程中,并被调用。

如果一切正常,App运行后,就会显示出 FFmpeg 音视频编解码器的信息。

原文 Android音视频: 引入FFmpeg - 掘金

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

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

相关文章

Minitab的单因子方差分析的结果

单因子方差分析概述 当有一个类别因子和一个连续响应并且想要确定两个或多个组的总体均值是否存在差异时&#xff0c;可使用 单因子方差分析。如果经检验&#xff0c;发现至少有一组存在差异&#xff0c;请使用单因子方差分析中的比较对话框来标识存在显著差异的组对。 例如&…

前端布局——垂直、水平居中

行内元素 方法一&#xff1a;给行内元素设置行高 <div class"box"><span>行内元素</span> </div> <style type"text/css">.box{width: 100%;height: 200px;background-color: orange;line-height: 200px;text-align: cent…

代码随想录算法训练营第三天| LeetCode203.移除链表元素、707.设计链表、206.反转链表

文章目录 一、203. 移除链表元素感受代码二、707.设计链表感受代码206.反转链表感受总结一、203. 移除链表元素 感受 我对这道题。从理论上来说太熟悉了。咸鱼讲数据结构常用的方法他都会讲。但是我没上机没写过。到后面上机还是写不出来。giao。 代码 第一次写,想说一下,…

LeetCode刷题:141. 环形链表

题目&#xff1a; 是否独立解答出&#xff1a;否&#xff0c;有思路&#xff0c;但是代码报错&#xff0c;参考解题代码后&#xff0c;修改通过 解题思路&#xff1a;利用循环与哈希表存储每一个节点&#xff0c;如果发现添加不进去说明&#xff0c;存在环&#xff0c;正常来说…

x3daudio1_7.dll如何恢复,这6个方法都能修复x3daudio1_7.dll丢失问题

x3daudio1_7.dll文件缺失”。那么&#xff0c;什么是x3daudio17.dll文件&#xff1f;它的作用和影响又是什么呢&#xff1f;本文将详细介绍x3daudio17.dll文件的定义、作用和影响&#xff0c;并提供6个修复方法来解决这个问题。 一、x3daudio1_7.dll是什么&#xff1f; x3dau…

推荐熊猫电竞赏金电竞系统源码

熊猫电竞赏金电竞系统源码&#xff0c;包含APP、H5和搭建视频教程&#xff0c;支持运营级搭建&#xff0c;这套源码是基于ThinkPHPUniaapp框架开发的。 系统是一套完整的电竞平台开发源码&#xff0c;包括赛事管理、用户系统、竞猜系统、支付系统等模块。源码结构清晰&#xff…

vue3+vite开发生产环境区分

.env.development VITE_APP_TITLE本地.env.production VITE_APP_TITLE生产-ts文件中应用 console.log(import.meta.env.VITE_APP_TITLE)在html中应用&#xff0c;需要安装 html 模板插件 pnpm add vite-plugin-html -Dvite.config.ts中 import { createHtmlPlugin } from v…

非常好用的个人工作学习记事本Obsidian

现在记事本有两大流派&#xff1a;Obsidian 和Notion&#xff0c;同时据说logseq也很不错 由于在FreeBSD下后两种都没有相关ports&#xff0c;所以优先尝试使用Obsidian Obsidian简介 Obsidian是基于Markdown文件的本地知识管理软件&#xff0c;并且开发者承诺Obsidian对于个…

算法-二分专题

文章目录 概念应用场景代码模板OJ练习寻找指定元素1题目描述输入描述输出描述样例题解 寻找指定元素2题目描述输入描述输出描述样例题解 寻找指定元素3题目描述输入描述输出描述样例题解 寻找指定元素4题目描述输入描述输出描述样例题解 寻找指定元素5题目描述输入描述输出描述…

Qt添加资源文件

ui->setupUi(this);//1. 使用本地文件&#xff1a;ui->actionasdasdas->setIcon(QIcon("本地绝对路径"));ui->actiona1->setIcon(QIcon("C:/Users/满满/Desktop/output/picture/1.jpg"));//2. 使用资源文件&#xff1a;ui->actionasdasd…

内 存 取 证

1.用户密码 从内存中获取到用户admin的密码并且破解密码&#xff0c;以Flag{admin,password}形式提交(密码为6位)&#xff1b; 1&#xff09;查看帮助 -h ./volatility_2.6_lin64_standalone -h 2&#xff09;获取内存镜像文件的信息 imageinfo ./volatility_2.6_lin64_stand…

自动化测试数据校验神器!

在做接口自动化测试时&#xff0c;经常需要从接口响应返回体中提取指定数据进行断言校验。 今天给大家推荐一款json数据提取神器: jsonpath jsonpath和常规的json有哪些区别呢&#xff1f;在Python中&#xff0c;json是用于处理JSON数据的内置模块&#xff0c;而jsonpath是用…

LLaMA-Factory添加adalora

感谢https://github.com/tsingcoo/LLaMA-Efficient-Tuning/commit/f3a532f56b4aa7d4200f24d93fade4b2c9042736和https://github.com/huggingface/peft/issues/432的帮助。 在LLaMA-Factory中添加adalora 1. 修改src/llmtuner/hparams/finetuning_args.py代码 在FinetuningArg…

【Leetcode】2085. 统计出现过一次的公共字符串

文章目录 题目思路代码 题目 2085. 统计出现过一次的公共字符串 思路 使用两个哈希表 words1Count 和 words2Count 分别统计两个数组中每个单词的出现次数。然后遍历 words1Count 中的每个单词&#xff0c;如果该单词在 words1 中出现了一次&#xff0c;且在 words2 中也出…

小红书年终“礼物营销”玩法:种拔一体,实现品效破圈

恰逢年末&#xff0c;用户送礼需求旺盛&#xff0c;小红书推出“礼物季”&#xff0c;品牌们纷纷入局&#xff0c;话题上线18天浏览量破9亿。“礼物营销”覆盖全年营销节点&#xff0c;贯穿始终&#xff0c;礼赠场景下用户消费决策链路缩短&#xff0c;种拔一体&#xff0c;帮助…

Android 集成firebase 推送(FCM)

1&#xff0c;集成firebase 基础 1>googleService文件 2>项目级gradle 3>app级gradle 4>setting 2&#xff0c;推送相关 重点&#xff1a; 源文档&#xff1a;设置 Firebase Cloud Messaging 客户端应用 (Android) (google.com) /*** 监听推送的消息* 三种情况…

el-tree多个树进行节点同步联动(完整版)

2024.1.11今天我学习了如何对多个el-tree树进行相同节点的联动效果&#xff0c;如图&#xff1a; 这边有两棵树&#xff0c;我们发现第一个树和第二个树之间会有重复的指标&#xff0c;当我们选中第一个树的指标&#xff0c;我们希望第二个树如果也有重复的指标也能进行勾选上&…

Qt 调试体统输出报警声

文章目录 前言一、方法1 使用 Qsound1.添加都文件 直接报错2.解决这个错误 添加 QT multimedia3. 加入代码又遇到新的错误小结 二、第二种方法1.引入库 总结 前言 遇到一个需求&#xff0c;使用Qt输出报警声&#xff0c;于是试一试能调用的方法。 一、方法1 使用 Qsound 1.…

什么是金融RPA?金融RPA解决什么问题?金融RPA实施难点在哪里?

什么是金融RPA&#xff1f;金融RPA&#xff0c;即金融领域的机器人流程自动化&#xff0c;是一种利用软件机器人来代替人工完成重复性劳动任务的技术。它能够通过模仿最终用户在电脑上的手动操作方式&#xff0c;实现自动化处理大量重复、规则明确的业务流程&#xff0c;如账务…

44-js return返回值,全局作用域,局部作用域,隐式作用域,变量的生命周期,delete释放内存

1.return返回值:函数执行后剩下结果就是返回值。 function fn(a,b,c){//return返回值return(a+b+c);// console.log("aaa"); //return之后的值都不在执行了// alert("bbb"); //return之后的值不在执行了}console.log(fn(1,2,3)*10); 2.作用…