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

news2024/10/6 20:30:45

文章目录

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

概述

在这里插入图片描述

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

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() // function2

var 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) // 4
	return 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]) // 1
	arguments[1] = 2 
	console.log(b) // 2
}

test(0,0)

// 例2
function test1(a,b) {
	a = 1;
	console.log(arguments[0]) // 1
	arguments[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)

第一步,创建OA对象

const OA = {}

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

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

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

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

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

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

开始执行函数体

function test (a, b) {
	console.log(a); // 直接从OA里拿a:  function a() {}
	console.log(b) // 直接从OA里拿b: undefined
	var a = 2; // 拆分成两部,`var a;a = 1;` `var a;`已经在第二步中完成了,剩下`a = 2`,将OA的a赋值为2
	console.log(a) // 直接从OA里拿a:  2
	function a () {}; // 已经在第四步执行了
	console.log(a) // 直接从OA里拿a:  2
	console.log(b)  // 直接从OA里拿b: undefined
	var b = function b() {} // 拆分成两部,`var b;b = function b() {};` `var b;`已经在第二步中完成了,剩下`b = function b() {}`,将OA的b赋值为 function b() {}
	console.log(b) // // 直接从OA里拿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 = 0
		c = 1
		console.log(c, d)
		function e() {}
		var f = 0;
	}
	
	test1(3, 4)

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

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

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

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

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

const OA = {
	c: 3,
	d: function d() {},
	f: undefined
	e: function e() {}
}

开始执行代码

	function test1(c, d) {
		console.log(c, d) // 直接从OA里拿c和d // 3 , function d() {},
		console.log(f) // 直接从OA里拿f undefined
		var c = function() {} // 将OA里的c赋值为function() {}
		function d() {} // 在第四步执行了
		console.log(c, d) // 直接从OA里拿c和d function() {} function d() {}
		var d = 0 // 将OA里的d赋值为0
		c = 1 // 将OA里的c赋值为1
		console.log(c, d) // 1 0
		function 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() {}
}

var aa = 3;
function bb() {};
var dd;
function test3(aa, bb) {
	console.log(aa) // 1
	console.log(bb) // 2
	dd = 3;  // AO中有dd,改AO中的dd 
	console.log(dd) // AO中有dd,取AO中的dd  3 
	aa = 4;
	bb = 5;
	function dd() {} // 这一步相当于有了自己的dd
	console.log(aa); // 4 
	console.log(bb); // 5
	console.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.coloradmin.cn/o/1193255.html

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

相关文章

深度学习 opencv python 实现中国交通标志识别 计算机竞赛_1

文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 &#x1f525; 优质…

[极客大挑战 2019]BuyFlag 1(两种解法)

题目环境&#xff1a; FLAG NEED YOUR 100000000 MONEY flag需要你的100000000元 F12瞅瞅源代码&#xff1a; if (isset($_POST[password])){ $password $_POST[password]; if (is_numeric($password)) { echo "password cant be number" } elseif ($pas…

Postman的环境变量和全局变量

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 多种环境&#xff1a;开发环境、测试环境、预发布环境、生产环境&#xff0c;可以用环境变量来解决。 今天的分享就到这里&a…

『 Linux 』进程概念

文章目录 &#x1f5de;️ 冯诺依曼体系结构 &#x1f5de;️&#x1f4c3; 为什么在计算机当中需要使用内存充当中间介质而不使CUP与外设直接进行交互?&#x1f4c3; CPU如何读取数据 &#x1f5de;️ 操作系统(Operating system) &#x1f5de;️&#x1f4c3; 操作系统如何…

LeetCode【30. 串联所有单词的子串】

给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如&#xff0c;如果 words ["ab","cd","ef"]&#xff0c; 那么 "abcdef&…

NZ系列工具NZ06:VBA创建PDF文件说明

我的教程一共九套及VBA汉英手册一部&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到数据库&#xff0c;到字典&#xff0c;到高级的网抓及类的应用。大家在学习的过程中可能会存在困惑&#xff0c;这么多知识点该如何组织…

2022美亚杯团队赛

2022美亚杯团体赛 - XDforensics-Wiki 2022 美亚杯 团体赛AGC部分资格赛服务器部分 所有服务器部分解题思路_2022美亚杯团体赛复盘-CSDN博客 目录 AGC 1 2 Media Sever挂载 3 ssh登入的看法 PTS 4 5 ssh日志 6 7 查看docker列表 8 查看docker运行 9 建立网站…

《DevChat:AI编程助手引领开发新潮》

1. DevChat是什么&#xff1f; DevChat是一款由思码逸打造的AI编程工具&#xff0c;致力于提升开发者的编程效率。它集成了多种主流大模型&#xff0c;包括ChatGPT、Codex等&#xff0c;支持自然语言编程、代码编写、代码生成、代码补全等功能。DevChat的最大优势在于一站式服…

竞赛 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

【Hadoop实战】Hadoop指标系统V2分析

Hadoop指标系统V2分析 文章目录 Hadoop指标系统V2分析架构主要组成部分根据图表解释数据流向指标过滤JMX的应用开启指标系统的组件指标项说明 使用HTTP&#xff08;JMXJsonServlet&#xff09;获取指标接口调用方式GET查询的逻辑数据的来源&#xff0c;以及更新的原理 架构 在…

Leetcode2246. 相邻字符不同的最长路径

Every day a Leetcode 题目来源&#xff1a;2246. 相邻字符不同的最长路径 解法1&#xff1a;树形 DP 如果没有相邻节点的限制&#xff0c;那么本题求的就是树的直径上的点的个数&#xff0c;见于Leetcode543. 二叉树的直径。 考虑用树形 DP 求直径。 枚举子树 x 的所有子…

开发ios电脑app的费用受到哪方面的影响?

开发iOS电脑应用程序的费用受到多方面的影响&#xff0c;包括市场需求、功能复杂度、设计要求、开发人员经验、市场竞争以及后期维护等因素&#xff0c;下面我们将详细介绍这些影响因素&#xff0c;帮助您更好地了解开发iOS应用程序的费用构成。 一、市场需求 市场需求是影响…

【JavaEE初阶】 TCP三次握手四次挥手(超详细版)

文章目录 &#x1f334;三次握手四次挥手总览&#x1f6eb;三次握手&#xff08;建立连接&#xff09;&#x1f6a9;为什么要三次握手&#x1f4cc;解决彼此双发彼此认同的问题&#x1f4cc;验证双方的接听发送能力是否正常 &#x1f6a9;建立连接阶段涉及到的两个重要状态: &a…

iOS 设置图标和upload包时显示错误

右键-show in finder-AppIcon.appiconset-然后替换图片 然后遇到个问题 就是图片不能有alpha [Xcode]应用图标&#xff1a;ERROR ITMS-90717: “Invalid App Store Icon. The App Store Icon in the asset catalog in x… 具体操作&#xff1a;只需确保【AppIcon】图片集中不…

【23真题】简单!原题很多!211!

今天分享的是23年内蒙古869的信号与系统试题及解析。 本套试卷难度分析&#xff1a;22年内蒙古大学869考研真题&#xff0c;若有需要&#xff0c;戳这里自取&#xff01;该院校是考察通信原理信号的&#xff0c;从信号部分来看&#xff0c;本套试题内容难度中等偏下&#xff0…

类图复习:类图简单介绍

入职新公司在看新项目的代码&#xff0c;所以借助类图梳理各个类之间的关系&#xff0c;奈何知识已经还给了老师&#xff0c;不得不重新学习下类图的相关知识&#xff0c;此处将相关内容记录下方便后续使用。 文章目录 类图语法类与类的关系画类图 类图语法 语法描述public-pr…

电机应用-无刷直流电机

无刷直流电机 无刷直流电机&#xff08;Brushless Dirent Current Motor&#xff0c;简称BLDCM&#xff09;由电动机主体和驱动器组成&#xff0c;无电刷和无换向器&#xff0c;是除了有刷电机外用得最多的一种电机。 无刷直流电机不使用机械的电刷装置&#xff0c;采用方波自控…

网络安全专业的就业方向有哪些?

网络安全专业的就业方向有哪些&#xff1f; 网络安全专业毕业生就业较多&#xff0c;可以从事计算机科学与技术、信息与通信、电子商务、互联网金融、电子政务等领域的相关工作。还可以从事政府机关事业单位、银行、保险等信息安全产品的研发、信息系统安全分析与设计、信息安…

Leetcode_3:无重复字符的最长子串

题目描述&#xff1a; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。 示例 2: 输入: s "bbbbb"…

STM32——端口复用与重映射概述与配置(HAL库)

文章目录 前言一、什么是端口复用&#xff1f;什么是重映射&#xff1f;有什么区别&#xff1f;二、端口复用配置 前言 本篇文章介绍了在单片机开发过程中使用的端口复用与重映射。做自我学习的简单总结&#xff0c;不做权威使用&#xff0c;参考资料为正点原子STM32F1系列精英…