JS学习笔记

认识JS

表单动态验证、网页特效、服务端开发(Node.js)、桌面程序(Electron)、App(Cordova)、控制硬件-物联网(Ruff)、游戏开发(cocos2d-js)

JS是一种

程序化、 面向对象(oop)、函数式编程(FP) 的语言

特点: 动态类型、单线程(一次只能做一件事)和非阻塞事件循环并发模型(长时间运行的任务放在后台,运行完成后加入主线程)

JS引擎和运行时(工作原理)

即时编译,立即转换成机器代码 然后立即执行

浏览器执行JS

浏览器分为两部分:渲染引擎(解析HTML和CSS)和 JS 引擎(逐行解释每一句源码形成抽象语法树AST,编译后形成机器代码,之后进行优化并重新编译)。

JS组成

ECMAScript:Javascript语法 规定了JS编程语法和基础核心知识

ECMAScript 语法

DOM 页面文档对象模型 :

BOM浏览器对象模型

书写位置

1.行内式 js

<input type="button" value="唐伯虎" οnclick="alert('...')”>

2.内嵌式js

3.引入外部js

快捷键

单行注释 ctrl+/ ,多行注释 shift+alt+a, 多行注释 vscode中修改

输出语言

浏览器弹出警示框 alert(msg) / console.log(msg) / prompt(info)

let和const

块作用域,在相同的作用域,或在相同的块中,通过 let 重新声明一个 var 变量是不允许的;通过 let 重新声明一个 let 变量是不允许的;在相同的作用域,或在相同的块中,通过 var 重新声明一个 let 变量是不允许的;在不同的作用域或块中,通过 let 重新声明变量是允许的;

const PI=3.1415926; 后就不能更改常量原始值 但是可以更改常量对象的属性

const car={type="porsche", model="911", color="Black"}

car.color = "white";

car.owner="Bill";

JavaScript数据类型

字符串、数字、布尔、对象Object、函数

typeof返回变量的类型。
instanceof返回 true,如果对象是对象类型的实例。

三种对象类型

对象、日期、数组

两种不能包含值的数据类型

null 、 undefined

**constructor** 属性返回所有 JavaScript 变量的构造器函数。

数字型转变字符串

1、 变量.tostring() 2、 String(变量) 3 、数字变量+’ ‘

字符型转换为数字型

1、 parseInt(变量)--输出整数、去掉单位 但是parseInt('rem120px') :NaN

2、 parseFloat() 不会去掉单位

3、利用Number(变量)转换

4、利用算数运算隐式转换 利用+ -/ * 比如 ’12‘-0

运算符

num=10 ++num +10 = 21 //先自加再返回值 num++ +10 = 20 //算完num再+1

实际开发中 用后置 单独成行

比较运算符

===:值和数据类型完全一致

console.log(18=='18') //true 默认转换数据类型 会把字符串型数据转换为数字型

逻辑运算符

&& || !

逻辑与短路中断:后面不再执行

除了0 ‘ ’ null undefined NaN 之外都为真

console.log(123 && 456) // 456 表达式1为真 返回表达式2;如果表达式1为 假则返回表达式1

console.log(0&&1+2&&456*5678) // 0 以后都不再运算

逻辑或短路

表达式1为真 返回表达式1; 表达式1为假,返回表达式2

var num=0;

console.log(123 || num++); //123

console.log(num) //0 因为中断 num++没有运行到

运算符优先级:

先*/后+- 先&&后||

流程控制

三元表达式:条件表达式?表达式1:表达式2 //表达式为真 返回值为表达式1 表达式为假 返回表达式2

switch: 适合针对特定值的多分支语句 实现多选1

数组

  1. 利用new创建数组

    var arr = new Array();

  2. 利用数组字面量创建数组

var 数组名 = [1, 2, 'pink', true]

3.索引 arr[0] 是第一个元素

4.迭代

forEach()、map()、 filter()、 reduce():在每个数组元素上运行函数,以生成(减少它)单个值、

对象

对象也是变量,但包含很多值 以名称:值对方式书写

JavaScript 对象是被命名值的容器 值对被称为属性

const janas={

firstname : 'Jonas',

lastName:' Sch',

}

调用对象的属性: 对象名.属性 / 对象名['属性']

访问对象方法: 对象名.方法()

对象方法

方法是可以在对象上执行的动作

对象属性可以是原始值、其他对象以及函数。

对象方法是包含函数定义的对象属性。

const janas={

firstname : 'Jonas',

lastName:' Sch',

calcAge: function(birthYear){

return 2037-birthYear;

}

}

调用: jonas.calcAge(1991);

jonas['calcAge'] (1991)

javascript对象是易变的

var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"}
 
var x = person;
x.age = 10;           // 这将同时改变 both x.age 和 person.age

显示对象属性

  • 按名称显示对象属性

    person.name

  • 循环显示对象属性

    for(let x in person){

    txt += person[x]+" "

    }

  • 使用 Object.values() 显示对象

    通过使用 Object.values(),任何 JavaScript 对象都可以被转换为数组:

const person = {
  name: "Bill",
  age: 19,
  city: "Seattle"
};

const myArray = Object.values(person);
document.getElementById("demo").innerHTML = myArray;//Bill,19,Seattle

 · 使用 JSON.stringify() 显示对象

任何 JavaScript 对象都可以使用 JavaScript 函数 JSON.stringify() 进行字符串化(转换为字符串)

const person = {
  name: "Bill",
  age: 19,
  city: "Seattle"
};

let myString = JSON.stringify(person);//{"name":"Bill","age":19,"city":"Seattle"}

对象访问器

get 和 set

有get 可以属性形式访问

  • 它提供了更简洁的语法

  • 它允许属性和方法的语法相同

  • 它可以确保更好的数据质量

  • 有利于后台工作

对象构造器(构造函数)

因为我们创建对象只能创建一次,那么为了不再重复代码,就使用构造函数

构造函数名首字母必须大写!!构造函数不需要return!!

在构造器函数中,this 是没有值的。它是新对象的替代物。 当一个新对象被创建时,this 的值会成为这个新对象。

function Person(first, last, age, eye) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eye;
}
//new创建相同类型的对象
var myFather = new Person("Bill","Gates",62,"blue");
var myMother = new Person("Steve","Jobs",56,"green");
//为新对象添加属性 只有新对象 有这个属性 但是无法为对象构造器添加新属性
myFather.nationality = "English";
//与向已有对象添加新方法不同,您无法为对象构造器添加新方法。
//必须在构造器函数内部向一个对象添加方法:
function Person(firstName, lastName, age, eyeColor) {
    this.firstName = firstName;  
    this.lastName = lastName;
    this.age = age;
    this.eyeColor = eyeColor;
    this.changeName = function (name) {
        this.lastName = name;
    };
}

Map

JavaScript 对象 vs Map

JavaScript 对象和 Map 之间的差异:

对象Map
Size对象没有 size 属性Maps 有 size 属性
键类型对象键必须是字符串(或符号)Map 键可以是任何数据类型
键顺序对象键没有很好地排序Map 键按插入排序
默认对象有默认键Map 没有默认键

Set

Set 是唯一值的集合。

每个值在 Set 中只能出现一次。

一个 Set 可以容纳任何数据类型的任何值

函数

函数调用

1.以函数形式调用函数

function myFunction(a, b) {
    return a * b;
}
myFunction(10, 2);           // 将返回 20

2.作为方法调用对象

var myObject = {
    firstName:"Bill",
    lastName: "Gates",
    fullName: function () {
        return this.firstName + " " + this.lastName;
    }
}
myObject.fullName(); 

3.通过函数构造器来调用函数

如果函数调用的前面是 new 关键字,那么这是一个构造函数调用。

它看起来像你创建一个新的函数,但由于 JavaScript 函数是对象,你实际上创建一个新对象

// 这是函数构造器:
function myFunction(arg1, arg2) {
    this.firstName = arg1;
    this.lastName  = arg2;
}

// 创建了一个新对象:
var x = new myFunction("Bill", "Gates");
x.firstName;                             // 会返回 "Bill"

call()

使用 call() 方法,

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName:"Bill",
    lastName: "Gates",
}
var person2 = {
    firstName:"Steve",
    lastName: "Jobs",
}
person.fullName.call(person1);  // 将返回 "Bill Gates"

JS闭包

全局变量通过闭包实现局部(私有)

计数器被这个匿名函数的作用域保护,并且只能使用 add 函数来修改。

闭包指的是有权访问父作用域的函数,即使在父函数关闭之后。

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add();
add();
add();

// 计数器目前是 3

JS类 

类不是对象,是对象的模板

class Car {
  constructor(name, year) {
    this.name = name;
    this.year = year;
  }
}

类方法

class Car {
  constructor(name, year) {
    this.name = name;
    this.year = year;
  }
  age() {
    let date = new Date();
    return date.getFullYear() - this.year;
  }
}

let myCar = new Car("Ford", 2014);
document.getElementById("demo").innerHTML =
"My car is " + myCar.age() + " years old.";

作用域

先查找当前范围 找不到再寻找全局范围

块(ES6) 只能使用 let 和 const

变量提升:可以看JavaScript变量提升详解_大前端工程师的博客-CSDN博客_javascript 变量提升

1.var 变量声明提前 但是赋值不会提前

2.function 是函数变量和赋值同时提升。

3.局部变量偷偷赋值:

我们在console.log(a)时候,js沿着作用域链在括号内寻找,找到了a,发现是undefined,但是js不甘心,继续沿着作用域链向上检索,终于搜寻到外面的形参声明赋值,然后输出10 也就是说作用域链向上查找不是查到声明就完的,如果js发现它是undefined的话还会继续向上找

4.箭头函数:箭头函数仅仅只会变量提升而已,因为()=>function关键字是不一样的,function是声明函数的关键字,()=>只是一个赋值的右值而已

this关键字

this指向问题,一般情况下this最终指向的是那个调用它的对象

1.全局作用域或者普通股函数中this指向全局对象window(定时器里this也是指向window)

2.方法调用中谁调用this指向谁

3.构造函数中this指向构造函数的实例

DOM

文档对象模型 通过DOM接口可以改变页面样式 结构 和内容

DOM树

一个页面就是一个文档 DOM中使用document表示

页面中所有标签都是元素,DOM中使用element表示

节点 页面中所有内容都是节点(标签、属性、文本、注释),DOM中使用node表示

DOM把以上内容都看作是对象

//console.dir() 打印返回的元素对象 可以更好的查看里面的属性和方法

1.getElementById 获取html的id元素

2.getElementsByTagName('li') 获取 某类标签元素 返回某类标签的集合

如果页面中只有一个li 返回的还是伪数组形式

【重要】

如果获取ol 里面的 li

通过获取某个父元素内部所有指定标签名的子元素

element.getElementsByTagName('标签名')

父元素必须是单个对象 必须指明是哪个对象,获取的时候不包括父元素自己

var ol  = document.getElementsByTagName('ol')  //[ol]
console.log(ol[0].getElementsByTagName('li')) //指明第一个ol

3.HTML5新增获取元素方式

通过类名获取元素

document.getElementsByClassName('box')
document.querySelector('.box')  //返回指定选择器的第一个元素对象
document.querySelector('#box')  //为ID时
document.querySelectorAll('.box')  //有两个box时,选择所有 返回指定选择器的所有元素对象集合

4.获取body

document.body  //返回body元素对象
document.documentElement  //返回html元素对象

JS事件

事件源、事件类型、事件处理程序

(1)事件源:事件被触发的对象 谁 按钮

var btn=document.getElementById('btn')

(2)事件类型 如何触发 什么事件 比如鼠标点击还鼠标经过还是 键盘按下

(3)事件处理程序 通过一个函数赋值的方式 完成

btn.onclick = function(){

alert('点秋香');

}

改变元素内容

element.innerText 会去除html标签 空格和换行

elemenet.innerHTML 不会去除html标签 保留空格和换行

这两个属性是可读写的

表单修改内容 用 input.value=' ';

点击一次后被禁用 用input/this.disabled=true;

获取属性值

div.id / div.getAttribute('demo')

有时我们会有自定义属性,比如index 那么使用getAttribute比较方便

设置元素属性值

div.id="demo1" / div.setAttribute("属性","值")

😊H5自定义属性

为了保存并使用数据 有些数据只在页面中用到 而不需要存储在数据库中。

注意:data-开头为自定义属性

​​

兼容性获取 div.getAttribute('data-index') --------更喜欢用

H5新增(只能获取data- 开头的): div.dataset.index / div.dataset['index']

(dataset是一个集合index是data- 后的名称)

注意 若 data-后有两节 需要有驼峰命名法 div.dataset.listName / div.dataset['listName']

利用层级关系获取元素

之前都是用DOM提供的方法获取元素 逻辑性不强且繁琐-之后介绍父子关系的获取元素法

节点拥有节点类型nodeType、节点名称nodeName、节点值nodeValue这三个属性

元素节点 nodeType=1 属性节点 nodeType=2 文本节点 nodeType=3 文本节点包括文字、空格、换行等

----实际开发中主要获取元素节点(标签)

  1. 父级节点 node.parentNode (亲爸爸) 如果找不到则返回为空

  2. 子节点 parentNode.childNodes (注意s) 得到所有子节点包括文本 和元素 但我们只需要元素节点,需要专门处理:parentNode.children 获取所有子元素节点

    第一个子节点: .firstElementChid

    最后一个子节点: lastElementChild 但是存在兼容性问题

    实际开发: parentNode.children[0] parentNode.children[ parentNode.children.length-1]

  3. 兄弟节点 node.nextSibling 包含文本节点 previousSibling 下一个元素:node.nextElementSibling 上一个:node.previousElementSibling 有兼容性问题自己封装

  4. 创建节点 动态创建节点 document.creaElement('tagName')

    添加元素: 父级加一个子级 ul.appendChild(li) 添加到父节点的指定节点前: 父节点.insertBefore(child, 指定元素) child需要document.createElement('li') 创建

  5. 删除节点

    node.removeChild() 从DOM删除一个子节点 返回删除的节点

  6. 复制节点 node.cloneNode()

    var ul = document.querySelector('ul');
    ​
    var lili = ul.children[0].cloneNode();//括号为空是浅拷贝 只复制标签  不复制里面的内容
    //括号里面加个 true 就会复制节点
    ​
    ul.appendChild(lili);

  7. 创建元素

    (1) document.write() 如果页面文档流加载完毕 再调用这句话会导致页面重绘

       (2)element.innerHTML 是拼接字符串 比document.createElement耗时

事件高级

注册事件

1传统 :以on开头 比如onclick 特点 注册事件的唯一性

2监听: addEventListener() IE9之前不支持 可以用attachEvent()代替 特点:同一个元素同一个事件可以注册多个监听器 按注册顺序依次执行。

btns[1].addEventListener('click', function(){  //或者调用函数名 不需要加小括号
    alert(22);
})

删除事件

1传统 divs.onclick =null

2divs[1].removeEventListener('click', fn) //fn是函数名

DOM事件流

捕获阶段 document -> html -> body -> father -> son 元素.addEventListener('click', function(){}, true) 第三个参数为true

冒泡阶段 与捕获阶段反着来 第三个元素为false

第三个参数省略 属于冒泡阶段 ,点击了子元素 即使没有点击父元素但是还是会触发。

注意:

onblur onfocus onmouseenter onmouseleave 是没有冒泡的

事件对象

event就是一个事件对象 写到侦听函数中,小括号里面 当形参来看

事件对象只有有了事件才会存在。它是系统自动创建 不需要传递参数

事件对象 是我们事件的一系列相关数据的集合 比如鼠标点击里面 包含鼠标的相关信息,比如鼠标坐标....

btn.onclick=function(event/e){
//有兼容性问题    ie678只能window.event
  e = e || window.event;//用的少
  console.log(e);
}

e.target() 触发事件对象(比如点击谁就返回哪个元素) this 返回的是绑定事件的对象(元素)

阻止默认行为 e.preventDefault()

组织冒泡 e.stopPropagation()

事件委托/代理

例子: 快递站点 自行领取

原理:不是每个 子节点单独设置事件监听器 而是事件监听器设置在父节点上 然后利用冒泡原理设置每个子节点

ul.addEventListenner('click',function(e){}) // 给父节点设置监听器 那么点击任何li 都会有反应

e.target() 可以获得点击对象 (具体的li)

禁止鼠标右键菜单

document.addEventListener('contextmenu', function(e){
​
e.preventDefault();
​
})

禁止选中文字

document.addEventListener('selectstart', function(e){
​
e.preventDefault();
​
})

鼠标事件坐标

e.clientX e.clientY (相对于可视区域) | e.pageX e.pageY (相对于文档区域 拖动滚动条会变化) | e.screenX e.screenY 相对于电脑屏幕

键盘事件

传统都加on 一下的监听器写法

1.keyup 按键弹起 keydown 按键按下 keypress 按键按下 但是它不识别功能键 ctrl shift等 ---keyup事件触发时 文字已经落入文本框内 而另外两个

执行顺序:keydown -》 keypress -》 keyup

2.键盘事件对象

keyCode判断用户按下哪个键的ascii码值

keypress区分大小写 keydown和keypress 不区分

BOM

BOM概述

浏览器对象模型 提供了独立于内容而与浏览器窗口进行交互的对象 核心对象是window。比如页面大小发生变化 是window在操作,浏览器厂商自己定义。

window 对象的常见事件

1.window.onload()=function(){} 文档加载完毕才调用该事件,但是只能写一次,写多次以最后一个window.onload 为准

2.window.addEventListener(’load‘, function(){}) 多个不会冲突

3.document.addEventListener('DOMContentLoaded',function(){})

仅当DOM加载完成 不包括样式表 图片 flash等

4.调整窗口大小

window.addEventListener('resize',function(){})

当窗口小于一个大小时 隐藏某个值 完成响应式布局

window.innerWidth <= 800

JS执行机制 JS Async(异步)

JS同步任务会放在主线程执行栈内

异步任务是通过回调函数来实现,添加到任务队列中。

先执行同步任务,遇到回调函数放到任务队列中,一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

定时器

1.window.setTimeout(funciton(){}, 2000) 2秒之后调用此函数 可以省略时间 默认0 ; 函数可以写函数名

2.停止定时器 window.clearTimeout(timeoutID)

3.window.setInterval(回调函数,时间间隔 ) 反复调用一个函数

window.clearInterval(timeoutID)

setTimeout()

在使用 JavaScript 函数 setTimeout() 时,可以指定超时时执行的回调函数:

//三秒后执行myFunction函数
setTimeout(myFunction, 3000);
//或者传递整个函数
setTimeout(function() { myFunction("I love You !!!"); }, 3000);
​
function myFunction() {
  document.getElementById("demo").innerHTML = "I love You !!";
}

setInterval(myFunction,1000) 每秒间隔

等待文件

如果您创建函数来加载外部资源(如脚本或文件),则在内容完全加载之前无法使用这些内容。

这是使用回调的最佳时机。

此例加载一个 HTML 文件 (mycar.html),并在文件完全加载后在网页中显示该 HTML 文件:

function myDisplayer(some) { document.getElementById("demo").innerHTML = some; }

function getFile(myCallback) { let req = new XMLHttpRequest(); req.open('GET', "mycar.html"); req.onload = function() { if (req.status == 200) { myCallback(this.responseText); } else { myCallback("Error: " + req.status); } } req.send(); }

getFile(myDisplayer);

回调 某件事干完再回去调用函数

回调是作为参数传递给另一个函数的函数。

function myDisplayer(some){
    document.getElementById("demo").innerHTML = some;
}
function myCalculator(num1, num2, myCallback){
    let sum=num1+num2;
    myCallback(sum);
}
    myCalculator(5,5,myDisplayer);//不要使用括号

location对象

获取或设置窗体url 解析url

location属性

location.href 获取或设置整个URL host 主机域名 port返回端口号 pathname 返回路径 search 返回参数 hash 返回片段

location方法:

assign() 可以跳转页面(重定向) | replace() 替换当前页面 因为不记录历史 所以不能后退页面 | location.reload() 重新加载页面 相当于刷新按钮或者F5 参数为true 为强制刷新

navigator对象

包含浏览器类型

属性:userAgent

history对象

浏览器的历史记录进行交互 该对象包含用户访问过的 URL

back() forwaard() go(参数) 参数1前进一个页面 -1后退1个页面

PC端网页特效

元素偏移量offset

获取元素距离带有定位的父元素位置 父元素加relative, DOM中的parentNode不需要

自身大小(宽高)

注意:返回的数值都不带单位

client 元素可视区

动态得到该元素的边框大小 元素大小等

立即 执行函数 独立创建了一个作用域

不需要调用 写法:

1.

(function(a,b){
​
console.log(a+b);
​
})(1,2)

  1. (function(){}())

淘宝flexibleJS

pageshow 重新加载页面

之前学的load ,火狐中有往返缓存,保存了整个 页面的DOM和javascript , 后退按钮不能刷新页面,但是pageshow无论页面是否来自缓存。在重新加载页面中会在load

scroll系列属性 可以得到元素大小、滚动距离

scroll高度是内容大小 和 client中的高度是盒子大小

获取页面被卷的头部

mouseenter 和 mouseover区别

mouseover 经过自身盒子和子盒子都会触发 但是只经过自身盒子触发

因为mouseenter不会冒泡 经过子盒子时会冒泡到父盒子 -》鼠标离开 mouseleave

动画函数封装

核心原理 setInterval()

常见网页特效

classList

添加类 classList.add("") / classList.remove("") / classList.toggle('') 切换类

本地存储

1 数据存储在用户浏览器中

2设置读取不方便 甚至页面刷新不丢失数据

3 容量较大 sessionStorage 5M 、localStorage 20M

4 只能存储字符串 可以将对象JSON.stringfy() 编码后存储

sessionStorage

生命周期 为关闭浏览器窗口 同一个页面下的数据可以共享 以键值对存储

存储数据:sessionStorage.setItem(key, value)

获取数据:sessionStorage.getItem(key)

删除数据:sessionStorage.remove(key)

删除所有数据:sessionStorage.clear()

localStorage

1.生命周期 永久生效,除非手动删除否则关闭页面也会存在

2.生命周期 永久生效,除非手动删除否则关闭页面也会存在

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值