姬成JS入门
es6新特性:ES6经典入门到进阶 - 网易云课堂
浏览器两大组成:
shell(外观) 用户能操作的部分
内核 (看不到的)
渲染引擎
js引擎(处理js代码)
其他模块
JS:客户端脚本语言
1、解释性语言 (js、PHP、Python)
编译性(C、C++):通篇翻译,生成特定的文件 优点:快 不足:移植性不好(不跨平台)
注:Java 有虚拟机jvm .java–javac–编译–.class(可跨平台)
解释性:逐句翻译,不生成特定的文件 优点:跨平台 不足:稍微慢
2、单线程
3、ECMA标准(语法标准)
JS三大部分:ECMAScript、DOM、BOM
**JS执行队列:**轮转时间片(进程-线程)
主流浏览器及其内核:
浏览器 | IE | Chrome | Firefox | Opera | Safari |
---|---|---|---|---|---|
内核 | trident | webkit/Blink | Gecko | presto | webkit |
如何引入js:
1、页面内嵌script标签
2、外部js文件
注:结构、行为、样式相分离,故通常采用外部js文件
js基本语法:
变量(variable) var
var a=10, b=20, c, d;
命名规则:
1、_、字母、$开头
2、可以包含字母、数字、_、$
3、不可以用关键字、保留字
数据类型(弱类型语言):
原始值:number string Boolean undefined null
引用值:array object function date RegExp…
区别:
原始值 引用值 存放位置 栈(stack):先进后出 堆(heap):存储地址 赋值形式不同 基本语法:
语句结束加“;”
js语法错误会引发后续代码终止,但不会影响其他js代码块
js运算符:
计算运算符:
“+” :任何类型数据与字符串连接都是字符串类型
“-” “*” “/” “%” “=”
优先级"="最弱,“()”较高;
++
比较运算符(返回结果为Boolean):
< > == !=
字符串比较的是ASCII码 0:48 A:65 a:97
特例:a=NaN==NaN false
逻辑运算符: && || !
undefined,null,NaN,"",0,false==>false,其余为true
&&: 有两个表达式,第一个为转换为bool,若为真,返回第二个;若为假,返回第一个 var a=1&&2; var a=0&&2; //a=2 //a=0; 全真才为真,一假都为假 &&可以作为中断作用: 2>1 && document.write("hello");//类似if语句 data && fn(data);
if(条件){
}
if(){
}else if(){
}else{}
1 for
2 while
3 do{
}while()
switch case
switch(条件){
case 1:
...
break;
}
break
continue:终止本次循环,进行下一次循环
var arr=[1,2,f,"asd",undefined];
arr[i]
arr.length
数组循环
let arr = ['apple', 'banana', 'orange', 'tomato'];
arr.forEach((value, index, array) => {
console.log(value, index, array);
});
let arr2 = [
{
title: 'a',
read: 100,
hot: true
},
{
title: 'b',
read: 200,
hot: true
},
{
title: 'ca',
read: 300,
hot: true
}
];
let newArr = arr2.map((value, index, array) => {
console.log(value, index, array);
return "1";
});
console.log(newArr);
let arr3 = (function () {
let arr = [];
for (let i = 0; i < 100; i++) {
arr.push(i);
}
return arr;
}());
console.log("-----");
console.log(arr3);
let newArr1 = arr3.filter((val) => {
return val % 7 === 0;
});
console.log("*********");
console.log(newArr1);
let a = arr.some((value) => {
return value === "banana";
});
let b = arr.every((value) => {
return value === "banana";
});
console.log(a);
console.log(b);
let sum = arr3.reduce(((previousValue, currentValue, currentIndex, array) => {
return previousValue + currentValue;
}));
console.log(sum);
数组常用方法
var den={ 属性名 属性值 lastName : "Deng", age : 40, handsome : false,}den.age=25;console.log(den.age);
面向对象=对象+类+继承+消息通信
对象:对象是由一组属性值和在这组值上的一组操作组成;数据+对数据的操作
类:具有相同属性值和服务的对象归到一个类;每一个对象称为该类的实例,其具有相同的服务
消息通信:各个类的对象之间通过消息进行通信。
返回数据类型:number,string,boolean,object,undefined,function
显式类型转换:
Number();//不能转的转为NaNparseInt(data,进制);//以目标进制为基,转换为十进制 //从数字开始,读取到第一个非数字位;parseFloat();//读取到第一个非小数点的非数字位;String();toString();//undefined/null不能用toStringboolean();
隐式类型转换
isNaN();-->number();++/-- + -...//-->number()
不发生类型转换:
=== !==
eg:
typeof返回类型:number,string,Boolean,undefined,objecttypeof(typeof(a));//string特殊:typeof(null) object
其他类型转Boolean:
函数声明:function 函数名(){}函数表达式:(忽略函数名)var 函数名= function (){}调用 函数名();
function sum(a,b){ 形式参数-->形参 //var a;var b; var c=a+b; document.write(c); 实际参数-->实参}sum(1,2);
形参、实参个数可以不匹配
天生不定参,形参可以比实参多,实参也可以比形参多
arguments 这个是实参列表
function sum(a){ //argument--[11,2,3] argument.length //sum.length }sum(11,2,3)
函数结束条件:return
作用:结束函数;返回值
若未显式地设置函数的返回值,则函数会默认返回一个undefined值
若需要函数返回多个值,则只有将值组合成一个对象或数组进行返回
return;return a;return [a,b]
1、找规律
2、找出口
js运行三部曲:
1、语法分析
2、预编译 函数声明整体提升 变量 声明提升
3、解释执行
1、imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局变量所有
2、一切声明的全局变量,都是window的属性 var a=123==>window.a=123;
3、window是个对象,且是全局对象 GO(Global Object)===window
1、创建AO对象 Activation Object(执行期上下文)
2、找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3、将实参值和形参统一
4、在函数体里面找函数声明,值赋予函数体
注:先创建GO,运行到函数体,再创建AO
[[scope]]:每个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供JavaScript引擎存取,[[scope]]就是其中一个。
[[scope]]指的就是所说的作用域,其中存储了运行期(执行期)上下文(AO)的集合。
作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式连接,我们把这种连接叫做作用域链。
函数执行完后,其本身的AO会销毁
查找变量:从scope顶端开始查找
function a(){ function b(){ ... }}
a定义时,只产生GO;a执行时,再在顶端产生AO
b产生时,继承a的GO和AO,b执行时,再顶端产生自己的AO
当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄露。
闭包的作用:
实现共有变量 eg:函数累加器
可以做缓存(存储结构)
可以实现封装、属性结构化
模块化开发,防止污染全局变量
立即执行函数:(执行完函数立即释放)
只有表达式才能被执行
(functon (){}());或(functon (){})();(function (a,b,c){ var d=a+b*3+c*5-2; return d;}(1,2,3))
**解决闭包的方法:**用立即执行函数,闭包的方式解决闭包
两个闭包例子:
function a(){ function b(){ var bb=234; document.write(aaa); } var aaa=123; return b;}var glob=100;var demo=a();demo();
function text(){ var arr=[]; for(var i=0;i<10;i++){ arr[i]=function(){ document.write(i+" "); } } return arr;}var myArr=text();for(var j=0;j<10;j++){ myArr[j]();}解决方法(立即执行函数)function text(){ var arr=[]; for(var i=0;i<10;i++){ (function(j){ arr[j]=function (){ document.write(j+" "); } }(i)) } return arr;}var myArr=text();for(var j=0;j<10;j++){ myArr[j]();}
var Deng={ name:"deng", sex:40, health:100 smoke:function (){ console.log("dsd"); this.health--; } }
对象属性的增删改查
查:Deng.name;增:Deng.wife="liu";改:Deng.sex="female";删:delete Deng.name;
对象的创建方法
1、var obj={} plainObject 对象字面量/对象直接量2、构造函数(构造函数命名遵循大驼峰式规则,即所有单词首字母均大写) 1)系统自带的构造函数 new Object() var obj=new Object();==>var obj={}; 2)自定义 function Car(){ this.name = "BMW"; this.height = "1400"; this.health = 100; this.run = function (){ this.health--; } } var car1 = new Car();
构造函数内部原理
1、在函数体最前面隐式的加上this={}2、执行this.xxx=xxx;3、隐式的返回this
原始型赋属性,需要调用包装类。包装类用完后立即deletenew Numbe/String/Boolean();
原型定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的共同祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
prototype --原型
Person.prototype.property="men";或Person.prototype={}Person{}
prototype默认隐式属性
__proto__:Person.prototype;constructor构造器,指向对象的构造函数Person.prototype{ constructor:Person(){} }
原型链顶端Object.prototype
var object=Object.create(原型);
绝大多数对象最终都会继承自Object.prototype,除了Object.create(null);
eg:
var num = 123;num.toString();-->new Number(num).toString();Number.Prototype.__proto__ = Object.prototype
作用,改变this指向 借用别人的函数实现自己的功能
区别,传参列表不同
call需要把实参按照形参的个数传进去apply需要传一个argumentsPerson.call(obj,age,sex,hobbit);Person.apply(obj,[age,sex,hobbit]);
eg:
function Person(name, age, sex) { this.name = name; this.age = age; this.sex;}function Student(name, age, sex, tel, grade) { Person.call(this, name, age, sex); this.tel = tel; this.grade = grade;}var student = new Student("tom", 45, "male", 123, 2020);
圣杯模式:
function inherit(Target,Origin){ function F(){}; F.prototype=Origin.prototype; Target.prototype=new F(); Target.prototype.uber=Origin.prototype;//target的超类}inherit(Student,Person);var student=new Student();
注:模拟jQuery,实现方法的连续调用:
return this;
属性的拼接
obj.name --> obj["name"];eg:var num = 1;return this["name" + num];
for(var prop in obj){ //forEach console.log(prop); console.log(obj[prop]);}obj.hasOwnProperty(); //判断属性是否是对象自身的instanceof A instanceof B 看A对象的原型链上 有没有 B的原型,返回bool(B是构造函数)
1、函数预编译过程中this–>window;
2、全局作用域里this–>window;
3、call/apply可以改变this指向
4、obj.func();func()里面的this指向obj
argument.callee返回自身引用,argument.length
定义数组方式:
var arr=[];var arr=new Array();
改变原数组
push,pop,shift,unshift,sort,reverse,splice
push,添加数据,返回数组长度
pop,把数组的最后一位剪切,返回数组最后一位
shift/unshift,unshift在数组前加数据,shift在数组前删数据
sort,ASCII码升序
自定义排序规则 原理:冒泡排序
reverse,逆转数据
splice,arr.splice(从第几位开始,截取多少的长度,在切口处添加数据)
不改变原数组
concat,join
concat,拼接数组
toString
slice(从该位开始截取,截取到该位)
join(字符串) arr1字符串arr2字符串arr3 string.split(字符串);
forEach
forEach是 ES5 中操作数组的一种方法,主要功能是遍历数组,其实说穿了,就是 for 循环的加强版,该语句需要一个回调函数,作为参数。回调函数的形参,依次为,value:遍历的数组内容;index:对应的数组索引,array:数组本身。**
arr.forEach(function(value,index,array){ console.log(value); console.log(index); console.log(array); })
类数组的特性:
属性要为索引(数字)属性,必须要有length属性,最好再加上push;
var obj={ "0":'a'; "1":'b'; "2":'c'; "length":3, "push":Array.prototype.push, "splice":Array.prototype.splice}
类数组本质是对象
优点:将数组和对象的特点集在一起
缺点:数组的一些方法需要自己添加
在try里面的发生错误,不会执行错误后的try里面的代码
try{}catch(e) { //error error.message error.name console.log(e.name+":"+e.message);}
error.name的错误信息一共六种:
1、EvalError:eval()的使用与定义不一致2、RangeError:数值越界3、ReferenceError:非法或不能识别的引用数值4、SyntaxError:发生语法解析错误5、TypeError:操作数类型错误6、URIError:URI处理函数使用不当
浏览器基于es3+es5的新增方法
es5严格模式:es3和es5冲突部分用es5,否则用es3
es5.0严格模式启动:写在逻辑的最顶端"use strict";
就是一行字符串,不会对不兼容严格模式的浏览器产生影响。
es5严格模式不支持方法:with,arguments.callee,func.caller
with:改变作用域链,将参数对象放到作用域链的最顶端。可用于代码简化
es5严格模式
变量赋值前必须声明
局部this必须被赋值
拒绝重复属性和声明
DOM–>Document Object Model,是对HTML以及XML的标准编程接口。
对节点的增删查改
查://DOM、BOM系统自动生成的一组数据都是类数组形式
document代表整个文档
doucument.getElementById(’’);
doucument.getElementsByTagName(’’)[];
doucument.getElementsByName(’’)[];//不常用
doucument.getElementsByClassName(’’)[];//不常用,因为ie8及以下不兼容
.querySelector();//css选择器(‘div>span strong.demo’) 非实时的
querySelectAll();
遍历节点树 DOM对象的属性
parentNode:父节点,
childNodes:所有子节点,
firstChild,lastChild,
nextSibling:下一个兄弟节点 previousSibing:上一个兄弟节点
所有节点类型:
元素节点——1
属性节点——2
文本节点——3
注释节点——8
document——9
基于元素节点树的遍历
parentElement
children,返回当前元素子节点
firstElementChild,lastElementChild
nextElementSibling/previousElementSibling
节点的四个属性
nodeName
nodeValue,只有文本节点和注释节点有,值为文本内容,其他节点为null
nodeType,该节点的类型,只读
attributes,该节点的属性集合
节点的一个方法 Node.hasChildNodes();返回Boolean
原型链:document–>HTMLDocument.prototype–>Document.prototype
getElementById定义在Document.prototype上
getElementByName定义在HTMLDocument.prototype上
getElementByTagName定义在Document.prototype和Element.prototype上
document.body/head/documentElement分别指body,head,HTML
增:
插:
删:
替换:
Element节点的一些属性
Element节点的一些方法
Date:日期对象
创建
var date = new Date();
方法
eg:
var i = 0;var timer = setInterval(function () { console.log(i++); if (i > 10) { clearInterval(timer); }}, 1000)
Global
url编码:在数据传输中,将字符转为Unicode编码,每个字符通过%分隔开
encodeURI(); url编码decodeURI(); url解码
eval():将js的字符串转为js代码执行
窗口尺寸
window.pageXOffsetwindow.pageYOffset
可视区窗口的尺寸
window.innerWidthwindow.innerHeight
查看元素的几何尺寸
domEle.offsetWidth;domEle.offsetHeight; 注意:不包含margin
查看元素的位置
domEle.offsetLeft;domEle.offsetTop; 对于无定位父级的元素,返回相对文档的坐标;对于有定位父级的元素,返回相对于最近的有定位的父级的坐标
让滚动条移动
三个方法:
scroll(),scrollTo() scrollBy()区别:scrollBy会在之前的位置上累加
读写元素CSS属性
dom.style.prop
查询计算样式
事件——交互体验的核心功能
elem.onXxx = function (event) {} 基本等同于写在HTML行间上
obj.addEventListener(type,fn,false);eg: div.addEventListener("click", function () { console.log("a"); }, false)注:可以为一个事件绑定多个处理程序
解除绑定事件:
elem.onclick = null;
elem.removeEventListener(type,fn,false);注:若绑定匿名函数,则无法解除
事件冒泡
事件捕获
触发顺序:
focus,blur,change,submit,reset,select等事件不冒泡
取消冒泡
阻止默认事件
默认事件:表单提交,a标签跳转,右键菜单等
点击事件
焦点事件
加载事件
鼠标事件
键盘事件
选择和改变
表单事件
JavaScript异步加载的三种方案:
两种创建方式:
直接量
var reg = /abc/im; i:ingoreCase g:global,全局匹配(查找所有匹配而非在找到第一个匹配后停止) m:multiline,执行多行匹配
new RegExp(“正则表达式”);
reg.test(),检测是否匹配
str.match(reg),返回匹配数组
BOM:Browser Object Model 浏览器对象模型
BOM组成:
Windows对象:
创建:
方法:
let
const:和let特性一样
eg:
let [a, b, c] = [12, [5, 6]];console.log(a, b, c);
注:左右两边,结构格式要保持一致
let json = { name: 'tom', age: 45, job: 'stu'};let {name, age, job:a} = json;console.log(name, age, a); //a相当于job的别名
解构的时候可以给默认值
let [a, b, c = "默认值"] = ['tom', 45];console.log(a, b, c);
语法:` ${变量} `;
let name = "tom";let age = 45;let str = `name=${name},age=${age}`;
语法
() = > 单个语句
() = > { ... return 返回值;}
注:
eg:
单击此处什么也不会发生
当用户链接时,void(0) 计算为 0,但 Javascript 上没有任何效果。
# 包含了一个位置信息,默认的锚是**#top** 也就是网页的上端。
而javascript:void(0), 仅仅表示一个死链接。所以,该语句常用于超链接中,防止资源跳转
在添加时,innerHTML,浏览器会将innerHTML中的标签解析出来,而innerText则会将会整个字符串内容作为文本内容
在打印时,两者没有区别
function getContextPath() { let strPath = location.pathname; return strPath.substring(0, strPath.substr(1).indexOf('/') + 1);}
dom树(HTML标签)和渲染树(css文件)同时生成,之后再将两个树合并,渲染
因为js中有对于dom元素的操作,为了避免冲突,所以js会阻塞dom树的生成。如果js可以不对dom元素进行操作,可以通过添加“defer”或“async”异步加载js(前端是单线程的,浏览器是多线程的)
回调函数:被调用者回头调用调用者的函数,这种由调用方自己提供的函数叫回调函数。
eg:
在未来某个时刻,A函数t调用完成了,那么程序会回到它刚才离开的地方,并继续执行后半部分C函数。
Promise是异步编程的一种解决方案
promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。
创造promise实例后,它会立即执行。一般来说我们会碰到的回调嵌套都不会很多,一般就一到两级,但是某些情况下,回调嵌套很多时,代码就会非常繁琐,会给我们的编程带来很多的麻烦,这种情况俗称——回调地狱。这时候我们的promise 就应运而生、粉墨登场了。
Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。
eg:
Promise的构造函数接收一个参数:函数,并且这个函数需要传入两个参数:
then链式操作的用法
从表面上看,Promise只是能够简化层层回调的写法,而实质上Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,
eg:
catch的用法
我们知道Promise 对象除了then 方法,还有一个catch 方法,它是做什么用的呢?其实它和then 的第二个参数一样,用来指定reject 的回调。用法是这样:
效果和写在then 的第二个参数里面一样。不过它还有另外一个作用:在执行resolve 的回调(也就是上面then 中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。
"==="是绝对相等
跟==不同,当数据类型不同时, 不进行数据类型转换,直接返回false
null==undefined //truenull===undefined //falseNaN==NaN //falseNaN===NaN //false
class Person { name; age; constructor(name, age) { this.name = name; this._age = age; } static method1() { console.log('这是一个静态方法'); } method2() { console.log('这是一个类方法'); } getName() { return this.name; } setName(name) { this.name = name; } getAge(){ return this.age; } setAge(age){ this.age=age; }}