根据2024尚硅谷的最新Web前端学习路线和2024年黑马程序员前端学习路线进行的学习笔记整理之javascript篇
(持续更新中)
本人先是看的尚硅谷的前端js课程,把基础看完之后发现尚硅谷的js基础比较侧重于不同浏览器版本之间的兼容,用的很多方法都是比较老,后面就转跟黑马程序员的前端系列课程。
文章目录
前端开发环境搭建
为了方便在本地搭建前端项目,笔者通过VSCode进行前端代码的编写,参考教程如下:VScode前端环境搭建:https://blog.csdn.net/m0_75262940/article/details/141105423
js常见指令
数学内置函数
名称描述Math.ceil()向上取整Math.floor()向下取整,与parseInt()相似,但后者是可以进行字符串转整数的。Math.round()四舍五入Math.random()生成 [0,1) 之间的随机数Math.pow()幂运算
数组arr元素的增删及其他基本操作
名称描述arr.push(新增数据)将一个或多个元素添加到数组的
末尾
,并返回该数组的新长度(⭐⭐⭐)arr.unshift(新增数据)将一个或多个元素添加到数组的
开头
,并返回该数组的新长度arr.pop()将数组的
最后一个元素
弹出(也就是删除),并返回该元素的值arr.shift()将数组的
第一个元素
删除,并返回该元素的值arr.splice(操作的下标
(起始位置)
, 删除的个数)适合用于删除数组中间的元素
js数据类型
undefined, null, boolean, string, symbol, number and object
- 基本(值)类型: - string:任意字符串- number:任意数字- boolean: true/false- undefined: underfined- null: null
- 对象(引用)类型: - Object:任意对象- Function:一种特别的对象(可以执行)- Array:一种特别的对象(数值下标,内部数据是有序的)
需要注意的是:
- js中的变量都是保存在
栈内存
中的,基本数据类型的数值
直接在栈内存中存储,值之间是独立存在的; - 对象是保存到
堆内存
中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址
(对象的引用),如果两个变量保存的是同一个对象的引用(即同一个地址)时当一个通过一个变量修改属性时,另一个也会受到影响。 - 什么是对象字面量?
类型判断方法
- 基本类型: - typeof:直接判断并的得出类型 - 能判断:undefined / number / string / boolean / function- 不能判断:null / object (都是同一类型) object / array- instanceof:判断对象的具体类型 - a instanceof object:a(实例对象)是不是object这个构造函数的实例- a instanceof array:a(实例对象)是不是array这个数组对象的实例- ===:强制等于,可以判断undefined和null(只有一个值)
- 对象类型:用instanceof来判断
js声明变量的3种方式
var, let, const
- var:可以在整个程序中使用;若在函数中变量没有用var来声明的话,该变量将自动变为全局变量=>因此,一般函数内都要先声明变量,使其为具有局部作用域的变量。(因为比较老现在开发中尽量避免用var)
- let:只会在声明的范围内使用,并不会将当前值绑定到全局对象中(如:let a = 100; console.log(window.a)就不一定是100)
- const:是个永远不会改变的变量
var myNumber =5let ourNumber ="123"const pi =3.14
(1)以后声明变量我们优先使用哪个?
- const
- 有了变量先给const,如果发现它后面是要被修改的,再改用let
(2)为什么const声明的对象可以修改里面的属性?
- 因为对象是引用类型,里面存储的是地址,只要地址不变,就不会报错
建议数组和对象使用const来声明
(3)什么时候使用let声明变量?
- 基本数据类型的值或引用数据类型的地址发生变化时
- 比如 一个变量进行加减运算,eg. for循环中的i++
适用赋值运算符存储数值:
声明变量和分配变量是有区别的
js对变量大小写是敏感的
js中加分号";"可以更好区分是否换行,但不加也没关系
转义字符 \
CODEOUTPUT’单引号‘’双引号\反斜杠\n换行符\r回车\t制表符\b退格\f换页
函数
函数的属性和方法
函数是一段可重复使用的代码块,用于执行特定的任务。它可以接受输入参数(也可以没有参数),并返回一个值(也可以不返回值)。
函数就像是一个工具,通过调用它来执行特定的逻辑操作,这有助于提高代码的复用性和可维护性。
函数有
命名函数
(Named Functions)、
匿名函数
(Anonymous Functions)、
箭头函数
(Arrow Functions)、
立即执行函数表达式
(IIFE - Immediately - Invoked Function Expressions)、
构造函数
(Constructor Functions)和事件驱动中的
回调函数
(Callback Function)等。
其中匿名函数通常作为其他函数的参数(如回调函数)或者立即执行函数表达式(IIFE)。例如,作为回调函数用于数组的forEach方法
箭头函数
ES6中提供的一种更简洁的函数定义方式,并且它的
this
绑定与普通函数不同,是由其定义时所在的上下文决定的,而不是像普通函数那样在调用时确定。
这使得它在处理事件处理函数和回调函数等场景中,能够避免this指向混乱的问题。
例如传统的函数定义:
functionadd(x, y){return x + y;}
用箭头函数可以写成:
functionadd=(x, y)=> x + y;
立即执行函数(只会执行一次)
面试常考题:用工厂方法创建对象(批量创建对象)
局限性:使用工厂方法创建的对象,使用的构造函数都是Object,所以创建的对象都是Object这个类型,会导致我们无法区分出多种不同类型的对象。
构造函数(封装 多态)
比如:
var per = new Person();
此时,this指的就是新建的对象per,最终会作为返回值赋值给per
改进之后,可调用创建更多不同属性的对象:
跟工厂方法类似,但使用同一个构造函数创建的对象,成为一类对象,比如Person类和Dog类
其中,对象 instanceof 构造函数可以用于检查一个对象是否是一个类的实例(eg. per instanceof Person也就是判断人属不属于人的类型)。
使用同一个构造函数创建的对象,我们称为
一类对象
,也将一个构造函数称为
一个类
。我们将通过一个构造函数创建的对象,称为是该
类的实例
。
回调函数
面试常考题:函数对象的方法call()、apply() 和 bind()是每个 JavaScript 函数都具有的 3 个基本方法
(1) call() 函数:能改变函数内部this指向问题的函数
- 基本用法
var person ={fullName:function(){returnthis.firstName +" "+this.lastName;}}var person1 ={ firstName:"Bill", lastName:"Gates",}var person2 ={ firstName:"Steve", lastName:"Jobs",}person.fullName.call(person1);// 将返回"Bill Gates" ,直接传递函数的实参来改变this指针原本指向的值
- 实现原理:
面试手撕代码题
实现call函数需要将其绑定到function的原型上的,结合上面代码实现call函数功能,如mycall函数所示。Function.prototype.mycall=function(person_n){ person_n.fullName =this; person_n.fullName();}console.log(person.fullName.call(person2))// 将输出"Steve Jobs"
上面只是一个简单的实现方法,但不能够返回null的数据,想进一步了解可以参照这个大佬的视频:面试题 - 手撕JavaScript call apply bind 函数
(2)apply()函数:
- call和apply这两个方法都是函数对象的方法需要通过函数对象来调用
- 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this
- 不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递
(3)bind()
- bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)
- 改变this指向后不会立即执行,而是返回一个永久改变this指向的函数
具体解释和实现bind函数参照:面试官:bind、call、apply 区别?如何实现一个bind?
面试常考题:this和arguments是什么?有什么区别?
调用函数时隐含的属性有两个:this 和arguments
- this(调用函数的那个环境对象) this是函数的上下文对象,根据函数的调用方式不同会执向不同的对象(文章后面Dom环境对象中也有提到)。- 以函数的形式调用时,this是window- 以方法的形式调用时,this是调用方法的对象- 以构造函数的形式调用时,this是新建的那个对象- 使用call和apply调用时,this是指定的那个对象- 在全局作用域中this代表window
- arguments(封装实参的对象)- arguments和this类似,都是函数中的隐含的参数- arguments是一个类数组元素,它用来封装函数执行过程中的实参- 所以即使不定义形参,也可以通过arguments来使用实参- arguments中有一个属性callee表示当前执行的函数对象
Web APIs
Web APIs包括:
- DOM(Document Object Model)文档对象模型
- BOM(Browser Object Model)浏览器对象模型
Dom
Dom是什么?有什么作用?
- Dom是文档对象模型
- 可以操作网页内容,可以开发网页内容特效和实现用户交互
获取Dom元素的方法
window 对象的属性是代表的全局顶级对象,而D0M Manipulation按操作分为以下几种方式(使用不同的方法我们在dom树中选择一个元素):
- GetElementById()
- GetElementByClassName()
- getElementsByTagName()
按类名标签名分为:
因为强大的CSS选择器,此两个更容易用到
- querySelector(‘css选择器’) :参数包含一个或多个有效的css选择器
字符串
,比如document.querySelector('div')
可以用来抓取div标签或者获取该类名称。会选择第一个与选择器匹配的项,并返回该HTMLElement对象。如果没有匹配到,则返回null。 - querySelectorAll(‘css选择器’):参数包含一个或多个有效的css选择器
字符串
,比如document.querySelectorAll('ul li')
。会选择所有匹配项,并返回一个NodeList对象集合。
伪数组
通过以上querySelectorAll方法获取到的就是伪数组,只有一个元素也是伪数组。
形如下:
操作元素内容
- 对象.innerText 属性: - 将文本内容添加/更新到任意标签位置- 显示纯文本,
不解析
html标签 - 对象.innerHTML 属性: - 将文本内容添加/更新到任意标签位置- 显示纯文本,
解析
html标签
操作元素样式属性
- 通过style属性操作CSS:
对象.style.样式属性 = '值'
赋值时,如果需要,不要忘记加css单位(如 ‘500px’) 需要注意:此方法生成的是行内样式表,优先级比较高。 - 通过类名(className)操作CSS:
元素.className= 'active'
当修改的样式较多时可以用这个方法。因为class是关键字,所以这里用className代替。 此方法会覆盖前面的类名。如果想要两种样式都有,可以把两个类名都加上,像这样:<div class= “nav”><script>const div = document.querySelector('div') div.className ='nav box'</script></div>
- 通过classList操作类控制CSS:为解决className操作会覆盖前面类名的问题,可以通过classList追加和删除类名,这也是最常用的方法:
元素.classList.add('类名') // 追加一个类``````元素.classList.remove('类名') // 删除一个类``````元素.classList.toggle('类名') // 切换一个类
,此方法常用<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Document</title><style type="text/css"> div{ width:200px; height:200px; background-color: pink;}.box{ width:300px; height:300px; background-color: skyblue; margin:100px auto; padding:10px; border:1px solid #000;}.active{ color: red; background-color: pink;}</style></head><body><div class="box">文字</div><script>// 通过classList修改样式// 获取元素const box = document.querySelector('.box')// 追加类 add() 类名不加点,而且是字符串 box.classList.add('active')// // 删除类 remove() box.classList.remove('box')// 切换类 toggle() 有就加上,没有就删除 box.classList.toggle('active')</script></body></html>
操作样式属性小结:
操作元素表单属性
- 获取:DOM对象.属性名
- 设置:DOM对象.属性名 = 新值
表单.value = '用户名'``````表单.type = 'password'
- 自定义属性: 以"data-"开头的都是自定义属性 自定义属性案例:
- 定时器-间歇函数: - 定时器有什么用? 可以根据时间自动重复执行某些代码- 开启定时器:
setInterval(函数名, 间隔时间)
,每间隔一段时间调用这个函数,间隔时间单位是毫秒。同时,其返回的是一个id数字。setInterval(function(){ console.log('一秒钟执行一次')},1000)
或者functionfn(){ console.log('一秒钟执行一次')}setInterval(fn,1000)// setInterval(函数名, 间隔时间),函数名后面不跟括号,让定时器函数自己调用该函数。
- 关闭定时器:clearInterval(变量名)
,其中变量名为定时器的id号。
事件监听(绑定)
- 语法:
元素对象.addEventListener('事件类型',要执行的函数)
- 事件监听三要素: 1. 事件源:那个dom元素被事件触发了,要获取dom元素2. 事件类型:用什么方式出发,比如鼠标单击clik、鼠标经过mouseover、文本框输入内容等3. 事件调用的函数(事件处理程序):要做什么事
比如点击按钮触发弹窗事件:
const btn = document.querySelector('button')
btn.addEventListner('click',function(){alert('你好呀!')})
- 事件监听的版本扩展: 事件监听发展史:- DOM L0
事件源.on事件 = function(){}``````<button id="btn">按钮</button><script>var btn = document.getElementById("btn"); btn.onclick=function(){};</script>
- DOM L1事件源.addEventListener(事件, 事件处理函数)
区别:on方式会被覆盖,addEventListener方式可以绑定多次,拥有更多特性,推荐使用。
事件类型
此处案例参考黑马程序员js课程>>>Apis-day2-95-99轮播图完整版鼠标定时器切换、小米搜索框焦点事件、发布评论键盘事件等。
事件对象event
- 语法:如何获取 - 在事件绑定的回调函数的第一个参数就是事件对象- 一般命名为event、ev、e,比如
元素.addEventListener('click', function(e){})
- 常见事件对象属性: 名称描述type获取当前的事件类型clientX/clientY获取光标相对于浏览器可见窗口左上角的位置offsetX/offsetY获取光标相对于当前DOM元素左上角的位置key用户按下的键盘值,现在不提倡用keyCode(keyCode已废弃)
此处案例参考黑马程序员js课程>>>Apis-day2-100-101事件对象event、按下回车发布评论。
环境对象
- 什么是this? - 它代表当前函数运行时所处的环境,this就是这个对象,这个对象受当前环境影响。每个函数中都有this(环境对象),而this指向这个函数的调用者。
谁调用,this就指向谁
- 非严格条件下: - 普通函数this指向的是window;- 事件监听函数this指向的是调用者;- 箭头函数没有this。- 通过call、apply和bind方法this也可以改变指向。
回调函数
(上面函数部分已有提及)
事件流
- 事件流与两个阶段说明- 事件流:事件完整执行过程中的流动路径- 两个阶段:捕获阶段–>冒泡阶段 简单来说:捕获阶段是从父到子,冒泡阶段是从子到父
实际工作都是使用事件冒泡为主
- 事件捕获
- 事件冒泡
- 阻止冒泡 阻止冒泡流动传播一定是
事件对象e.stopPropagation()
- 解绑事件- on事件方式- addEventListener方式
版权归原作者 Dream_iy 所有, 如有侵权,请联系我们删除。