详解javaScript的事件中,复杂数据类型的传参(数组,对象,函数)

简介: 详解javaScript的事件中,复杂数据类型的传参(数组,对象,函数)

文章目录

在JavaScript这门编程语言学习中,有太多关键问题,比如如何传参,什么是变量提升,js代码预编译是怎么回事等等。要想成为一名优秀的js高手,这些内容是你不得不去认真研究和深挖的。今天我们就来具体看看这几件事,它到底是怎么回事儿。


一、何谓预编译,变量提升?

其实这一概念是javaScript非常基础而本质的内容,通过对一门编程语言 底层封装的一些内容、概念的深入研究。我们可以逐步接近语言的逻辑,本源,也能更好的理解编译这门语言的人当时的思路,这也算是跨越时空的对话了。


在js代码执行之前,会有一段时间。这段时间是用来给js代码做准备的。那么这段时间,我们称之为预编译时间。 而这段预编译时间,编译器干的最重要的事情就是给js代码进行变量提升,函数提升,以及形参实参的统一。



换句话说,女孩子出门游玩之前会有一段时间,这段时间是用来给她自己出去游玩做准备的。这段时间发生的最重要的事就是,化妆,换衣服等等。


预编译期间会将变量声明和函数声明提升到对应作用域的最顶端,只提升声明,不提升值!


如果是全局变量,则提升到全局作用域最顶端。如果是局部的变量,则提升到局部作用域的最顶端。


eg1:

      oo();
    function oo(){  
      console.log(`oo`);
    }
    // 此函数为普通函数,这样的函数预解析时有函数提升,所以可以在函数声明之前调用
    // 如果是下面这种写法,则预解析时,会被转化成上面这样,
    function oo(){  
      console.log(`oo`);
    }
    oo();

eg2

    var a = function(){
      console.log(`哈哈`);
    }
    a();
    // 函数表达式,只能在声明之后调用
    // 如果是var声明的函数表达式,具有变量提升的特点.但是只会返回undefined,因为只提升声明,不提升值
    // 如果是let,const声明的函数表达式,则不具备变量提升的特点.这是var特有的
    // 如果是上面这种写法,则预解析会被转化成下面这样
    var a;
    a = function(){
      console.log(`哈哈`);
    }
    a();

我相信js预解析,以及函数提升,变量提升到这应该是说明白了


二、复杂数据类型的传递

本人上一篇博客已经非常详细的解释了形参,实参,以及简单数据的传参。今天看看复杂数据类型的传递。


传参实质就是传实参给形参,最终让形参等于实参即可,形参用来接收实参的值,如此而已。


1.数组

代码如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div onclick="fun([1,2,'hh'],[45,'',47])">兔年大吉</div>
    <script>
    var a = 1;
    var b =8;
    function fun(a,b){
      console.log(a,b);
    }
    fun(a,b); 
    fun(3);
    </script>
  </body>
</html>

以上代码,我们是将数组[1,2,'hh'],[45,'',47]作为参数,进行传递的。


那么对应的a=[1,2,'hh'],而b=[45,'',47]


这个以数组作为参数传递,只有在点击的时候才会执行


另外一个问题就是,此函数被调用了两次,在不点击调用的情况下,自执行两次。

第一次执行fun(a,b)输出结果为1   8

此时a,b作为形参,而形参a,b两个变量被声明且赋值了,相当于初始化,分别给了a,b一个值,因此打印出来1   8

第二次执行fun(3)  输出结果为   3     undefined

这是因为,此时3作为实参,传给形参(a,b),但实参只有一个,而形参有两个。所以相当于给a赋值为3,b只声明未赋值,为undefined

总结:


形参和实参是一一对应关系,如同映射

当实参个数等于形参个数,则输出正确结果

当实参个数多于形参个数,只取形参个数

当实参个数小于形参个数,多出的形参只声明未赋值,属于未定义

  function full(person) {
        return person + '2' + person;
      }
  console.log(full());

上面输出 undefined2undefined

  function full(person) {
        return person + '2' + person;
      }
  console.log(full(1));

上面输出121

2.对象

代码如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div onclick="fn({name:'张三'})">法外狂徒</div>
    <script>
    function fn(n){
      console.log(n);
    }
    </script>
  </body>
</html>

这个就是点击事件以对象作为实参,进行传参的

当点击div以后,n={name:“张三”},这是一种赋值操作,只不过n作为变量没有被声明罢了

3.函数

这里我要重点说明一下


上面这两种写法,是完全不一样的,

A盒子表示将函数fk()的值作为参数进行传参

B盒子表示将函数fk作为参数进行传参

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div onclick="fm(fk())" >哈哈哈</div>
    <div onclick="fm(fk)" >哈哈哈</div>
    <script>
    function fk(){
      console.log(3);
      return 10;
    }
    function fm(result){  
      console.log(result);
      console.log( typeof result);              
      fk()                              
      result()
      console.log( result.prototype === fk.prototype );
    }
    </script> 
  </body>
</html>


第二个div,在这里将fk函数作为实参进行传参的时候,本质上fk是一个变量;

fk() = result();

result作为形参相当于一个声明,利用变量名调用函数;

result相当于   var  result = function fk(){};
总结

js预解析是非常重要的,这里面注意var与const和let的区别

以数组,对象等数据类型传参,记得注意参数之间存在一一对应关系

可以在调用函数的时候,把括号里面的内容看作实参,但本质上是变量。函数本身在某些场景下也可以理解为未声明的变量,但这仍然需要深度思考。函数作为实参是怎么传的,怎么执行的。文章只能给大家作为参考,最重要还是要自己深度思考。

创作不易,如果对你有帮助,希望不吝一键三连。


相关文章
|
9月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
350 19
|
11月前
|
编解码 JavaScript 前端开发
【Java进阶】详解JavaScript的BOM(浏览器对象模型)
总的来说,BOM提供了一种方式来与浏览器进行交互。通过BOM,你可以操作窗口、获取URL、操作历史、访问HTML文档、获取浏览器信息和屏幕信息等。虽然BOM并没有正式的标准,但大多数现代浏览器都实现了相似的功能,因此,你可以放心地在你的JavaScript代码中使用BOM。
329 23
|
11月前
|
JavaScript 前端开发 Java
【Java进阶】详解JavaScript事件
总的来说,JavaScript事件是JavaScript交互设计的核心,理解和掌握JavaScript事件对于编写高效、响应式的网页应用至关重要。
207 15
|
11月前
|
JavaScript
JS实现多条件搜索函数
JS封装的多条件搜索
|
JavaScript 前端开发
JavaWeb JavaScript ③ JS的流程控制和函数
通过本文的详细介绍,您可以深入理解JavaScript的流程控制和函数的使用,进而编写出高效、可维护的代码。
273 32
|
12月前
|
JavaScript 前端开发 API
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
12月前
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
12月前
|
数据采集 JavaScript 前端开发
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
用array.filter()来实现数据筛选、数据清洗和链式调用,相对于for循环更加清晰,语义化强,能显著提升代码的可读性和可维护性。博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
JavaScript 前端开发 测试技术
盘点原生JavaScript中直接触发事件的方式
本文全面探讨了原生JavaScript中触发事件的多种方式,包括`dispatchEvent`、`Event`构造函数、`CustomEvent`构造器、直接调用事件处理器以及过时的`createEvent`和`initEvent`方法。通过技术案例分析,如模拟点击事件、派发自定义数据加载事件和实现提示框系统,帮助开发者掌握这些方法在实际开发中的应用,提升灵活性与兼容性。
509 3
|
JSON 前端开发 JavaScript
JavaScript中对象的数据拷贝
本文介绍了JavaScript中对象数据拷贝的问题及解决方案。作者首先解释了对象赋值时地址共享导致的值同步变化现象,随后提供了五种解决方法:手动复制、`Object.assign`、扩展运算符、`JSON.stringify`与`JSON.parse`组合以及自定义深拷贝函数。每种方法都有其适用场景和局限性,文章最后鼓励读者关注作者以获取更多前端知识分享。
249 1
JavaScript中对象的数据拷贝