js 变量声明与赋值 笔试踩坑题

文章目录

    • 概述
    • 函数声明
    • 函数形参与实参
    • 函数预编译
      • 用一个例子说明一下,这四个步骤分别要干些什么。
      • 重复四个步骤,反复练习一下
    • 全局编译
    • 多重执行期上下文

概述

在这里插入图片描述

别小看变量声明与赋值,在所有的笔试中,基本都会考,这个要多变态就能多变态,但只要掌握基本的规律,我们就能游刃有余,面对一切困难。

var function1 = function() {console.log('abc')
}
function1()
var function1 = function abc() {console.log('abc')
}
function1()
abc()
var function1 = function() {console.log('function1')
}var abc = function function1() {console.log('abc')
}
function1()
abc()

上面三段代码分别会发生什么?

函数声明

函数有函数声明和函数表达式两种方式创建

函数表达式

var function1 = function() {console.log('function1')
}

函数声明

function function2() {console.log('function2')
}

以下代码会发生什么,当函数声明的名称和函数表达式赋值的变量相同时

function function1() {console.log('function2')
}
function1() // function3var function1 = function() {console.log('function1')
}function function1() {console.log('function3')
}function1() // function1

结论 函数声明整体提升,函数表达式只提升赋值的变量

以下两种函数有什么区别

var function1 = function() {console.log('function1')
}var function2 = function abc() {console.log('function2')
}function1() // function1
function2() // function2
abc() // 报错 

以上两种命名方式没区别。abc写与不写,基本没影响,写了也白写,通过abc()无法调用,abc未被声明,所以会报错 abc is not a function

唯一的区别在于function1.name === 'function1' // true function2.name === 'abc' // true
结论 函数声明赋值给变量时,函数声明就成了表达式,此时函数声明本身的名字将不重要。

函数形参与实参

arguments 就是实参 而 函数名xxx.length就可以拿到所有形参的数量

function test(a, b) {// 获取形参的数量console.log(test.length) // 2// 获取实参的数量console.log(arguments.length) // 4return a + b
}test(1,2,3,4) // 3

有了上面的启发,请你写一个函数能够返回所有传入参数的和

function sum() {let result = 0;for (let i = 0; i < arguments.length;i++) {result += arguments[i]}return result
}sum(1,2,3,4)

加深一点难度,请你将sum柯里化

function sum(a, b, c) {return a + b + c
}function curry(fun) {return function curryFun() {const args = arguments// 如果参数数量足够,直接返回函数调用结果, args是实参而fun.length就是形参所需的数量if(fun.length <= args.length) {return fun(...args)} else {// 当参数数量不够时,直接递归返回curried函数,当下一次curried函数被调用时,再判断参数是否足够return function(...nextargs) {return curryFun(...args, ...nextargs)}}}
}var curried = curry(sum)
var result = curried(1)(2)(3) // 6

看一下形参和实参之间的关系

// 例1
function test(a, b) {a = 1;console.log(arguments[0]) // 1arguments[1] = 2 console.log(b) // 2
}test(0,0)// 例2
function test1(a,b) {a = 1;console.log(arguments[0]) // 1arguments[1] = 2 console.log(b) // undefined
}
test1(0)

上面例1说明了形参与实参是有映射关系的,如果形参发生改变,对应的实参arguments也会发生变化,arguments如果发生变化,形参也会发生变化。但是形参和实参arguments是两个不同数据,它们只是有映射关系。

上面的例2与例1的唯一不同就是,实参传入的时候只有一个参数,所以形参中只有第一个参数a与实参arguments[0]完成了映射。第二个参数没有传,所以arguments[1]也就不存在,也无法与形参b完成映射。
这也从侧面证明了,形参与实参只是映射关系,本质上还是两个不同的数据。

函数预编译

发生在函数执行的前一刻。

  1. 创建AO(active object) 对象,又称为执行期上下文。
  2. 将形参的名称,和声明变量的名称,作为键值对的key,放入AO对象中,value为undefined。
  3. 将形参和实参统一。
  4. 在函数体里面找函数声明,并将函数赋值。

用一个例子说明一下,这四个步骤分别要干些什么。

function test (a, b) {console.log(a);console.log(b)var a = 2;console.log(a)function a () {};console.log(a)console.log(b)var b = function b() {}console.log(b)
}test(1)

第一步,创建AO对象

const AO = {}

第二步 将形参的名称,和声明变量的名称,作为键值对的key,放入AO对象中,value为undefined。
test的形参有 a b,声明变量也是 a b

const AO = {a: undefined,b: undefined
}

第三步,将实参赋值给形参,test(1) 也就是把1赋值给a

const AO = {a: 1,b: undefined
}

第四步, 在函数体里面找函数声明,并将函数赋值。只有一个函数声明function a () {};,所以

const AO = {a: function a() {},b: undefined
}

开始执行函数体

function test (a, b) {console.log(a); // 直接从AO里拿a:  function a() {}console.log(b) // 直接从AO里拿b: undefinedvar a = 2; // 拆分成两部,`var a;a = 1;` `var a;`已经在第二步中完成了,剩下`a = 2`,将AO的a赋值为2console.log(a) // 直接从AO里拿a:  2function a () {}; // 已经在第四步执行了console.log(a) // 直接从AO里拿a:  2console.log(b)  // 直接从AO里拿b: undefinedvar b = function b() {} // 拆分成两部,`var b;b = function b() {};` `var b;`已经在第二步中完成了,剩下`b = function b() {}`,将AO的b赋值为 function b() {}console.log(b) // // 直接从AO里拿b:  function b() {}
}

重复四个步骤,反复练习一下

	function test1(c, d) {console.log(c, d)console.log(f) var c = function() {}function d() {}console.log(c, d)var d = 0c = 1console.log(c, d)function e() {}var f = 0;}test1(3, 4)

熟悉以后直接从第二步开始
将形参的名称,和声明变量的名称,作为键值对的key,放入AO对象中,value为undefined。
test的形参有 c d,声明变量也是 c d f,重复的只管一个

const AO = {c: undefined,d: undefined,f: undefined
}

第三步,形参实参统一 传入的3和4 分别对应着c和d

const AO = {c: 3,d: 4,f: undefined
}

第四步, 在函数体里面找函数声明,并创建key 赋值给AO对象。
test1中的函数声明只有function d() {}function e() {}

const AO = {c: 3,d: function d() {},f: undefinede: function e() {}
}

开始执行代码

	function test1(c, d) {console.log(c, d) // 直接从AO里拿c和d // 3 , function d() {},console.log(f) // 直接从AO里拿f undefinedvar c = function() {} // 将AO里的c赋值为function() {}function d() {} // 在第四步执行了console.log(c, d) // 直接从AO里拿c和d function() {} function d() {}var d = 0 // 将AO里的d赋值为0c = 1 // 将AO里的c赋值为1console.log(c, d) // 1 0function e() {}var f = 0;}

难度升级,加入作用域

全局编译

  1. 创建GO(global object) 对象,又称为全局执行期上下文。
  2. 声明变量的名称,作为键值对的key,放入GO对象中,value为undefined。
  3. 在函数体里面找函数声明,并将函数赋值。

GO(global object)在不同的环境指代不同,在浏览器中,GO就是window,在node中GO就是global

多重执行期上下文

var aa = 3;
function bb() {};
var dd;
function test3(aa, bb) {console.log(aa)console.log(bb)dd = 3;console.log(dd)aa = 4;bb = 5;function dd() {}console.log(aa);console.log(bb);console.log(dd);
}test3(1, 2)
console.log(aa)
console.log(bb)
console.log(dd)

先创建GO(上面说的三个步骤)

const GO = {aa: undefined,dd: undefined,bb: function bb() {},test3: function test3() {...}
}

创建完成后,开始执行代码,执行到test3时,GO如下,创建AO(上面说的四个步骤)

const GO = {aa: 3,dd: undefined,bb: function bb() {},test3: function test3() {...}
}const AO = {aa: 1,bb: 2,dd: function dd() {}
}

函数test3的AO创建好以后,开始执行函数test3的函数体


var aa = 3;
function bb() {};
var dd;
function test3(aa, bb) {console.log(aa) // 1console.log(bb) // 2dd = 3;  // AO中有dd,改AO中的dd console.log(dd) // AO中有dd,取AO中的dd  3 aa = 4;bb = 5;function dd() {} // 这一步相当于有了自己的ddconsole.log(aa); // 4 console.log(bb); // 5console.log(dd); // 3
}test3(1, 2)
console.log(aa) // GO中有aa  3
console.log(bb) // GO中有bb  function bb() {}
console.log(dd) // GO中有dd  undefined

在这里插入图片描述

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

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

相关文章

JS-项目实战-鼠标悬浮变手势(鼠标放单价上生效)

1、鼠标悬浮和离开事件.js //当页面加载完成后执行后面的匿名函数 window.onload function () {//get:获取 Element:元素 By:通过...方式//getElementById()根据id值获取某元素let fruitTbl document.getElementById("fruit_tbl");//table.rows:获取这个表格…

git 命令行回退版本

git 命令行回退版本 git 命令行回退版本命令: 1.切换到需要回退的分支 git checkout branch-v2.0.02.更新远程分支 git fetch3.找到需要回退版本的版本号git revert a6914da55ff40a09e67ac2426b86f1212e6580eb4.清除工作区缓存git clean -df5.强制提交git push -f

解决Python requests库不支持发送可迭代对象的问题

在加班的路上&#xff0c;bug是那永远的陪伴。对于程序员来说&#xff0c;bug就像黑暗中的萤火虫&#xff0c;虽然微弱却永远指引着前进的方向。今天&#xff0c;我们要探讨的是Python requests库在处理可迭代对象时遇到的问题&#xff0c;这是一道让许多开发者头痛的难题。本文…

阿里云今年服务器是真便宜,看看哪些云服务器值得买!

2023年双十一&#xff0c;阿里云推出了一项令人惊喜的独家优惠活动&#xff01;在这次活动中&#xff0c;阿里云开放了老用户购买权限&#xff0c;以超低的价格购买云服务器ECS经济型e实例。这款服务器配置了2核2G内存、3M固定带宽和40G ESSD entry系统盘。而且&#xff0c;更棒…

一个用于操作Excel文件的.NET开源库

推荐一个高性能、跨平台的操作Excel文件的.NET开源库。 01 项目简介 ClosedXML是一个.NET第三方开源库&#xff0c;支持读取、操作和写入Excel 2007 (.xlsx&#xff0c; .xlsm)文件&#xff0c;是基于OpenXML封装的&#xff0c;让开发人员无需了解OpenXML API底层API&#xf…

技巧篇:在Pycharm中配置集成Git

一、在Pycharm中配置集成Git 我们使用git需要先安装git工具&#xff0c;这里给出下载地址&#xff0c;下载后一路直接安装即可&#xff1a; https://git-for-windows.github.io/ 0. git中的一些常用词释义 Repository name&#xff1a; 仓库名称 Description(可选)&#xff1a;…

hyper-v外部网络,ssh服务正常,可以ping通虚拟机,但是无法远程连接虚拟机。

问题&#xff1a; ssh服务正常&#xff0c;可以ping通虚拟机&#xff0c;虚拟机可上网&#xff0c;一切正常&#xff0c;但是无法远程连接虚拟机。 报错&#xff1a;Network error: Connection refused 解决&#xff1a; 在本机的网络设置中&#xff0c;这个东西不知道是什么…

呼叫中心有什么特色功能呢,okcc呼叫系统

随着科技的发展&#xff0c;智能呼叫中系统的出现帮助不少企业解决了问题&#xff0c;那么呼叫中心有什么功能呢&#xff1f; 1、来电弹屏 呼叫中心通话弹出屏功能与系统提供的CRM系统相结合&#xff0c;可根据通话号码自动匹配客户数据&#xff0c;通话显示用户历史服务记录或…

使用xlwings实现对excel表中指定列隔行求和

需要对上表中的营业额隔行求和&#xff0c;即橙色背景颜色的求和&#xff0c;无背景颜色的求和。 看了大佬的视频&#xff0c;有两种方法&#xff1a; 1.加辅助列 2.使用判断行的奇偶函数&#xff0c;然后在用sumproduct函数 在此&#xff0c;我使用xlwings对excel表中数据…

2023 年是无代码的一年,还要程序员吗?

从 Code 到 No Code&#xff0c;IT 界对简化代码开发的需求由来已久&#xff1a;过去数十年的发展历程中&#xff0c;在企业应用程序开发上&#xff0c;我们研发出工作流、智能业务流程管理系统、低代码/无代码、还有高生产力应用程序平台等应用开发形式。 有一句话在 IT 界流…

前后端交互案例,图书管理系统

先引入前端代码运行看看是否有问题 图书管理系统 定义前后端交互接口 1.登录 URL : /user/login 参数 : userName?&password? 响应 : true/false 2.图书列表展示 : URL : /book/getBookList 参数 : 无 响应 : List<BookInfo> 后端代码如下: package com…

盘点30个Python树莓派源码Python爱好者不容错过

盘点30个Python树莓派源码Python爱好者不容错过 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1LA4cLunntKW3qO5aok3xAQ?pwd8888 提取码&#xff1a;8888 项目名称 PiCar-raspber…