对象
Object.keys();
delete person.name; //删除对象中的一个属性
枚举对象属性:
for … in语句:
for(var 变量 in 对象){
}
全局作用域:指一个变量的作用范围。JS中一共有两种作用域,全局作用域和函数作用域。
直接编写在script标签中的JS代码,都在全局作用域。全局作用域在页面打开时创建,在页面关闭时销毁。在全局作用域中有一个全局对象window,我们可以直接使用,它代表是一个浏览器的窗口,它由浏览器创建。在全局作用域中创建的变量都会作为window对象的属性保存。创建的函数都会作为window对象的方法存在。
全局作用域中的变量都是全局变量,在页面的任意位置都可以访问的到。
变量的声明提前:
使用var关键字声明的变量,会在所有的代码执行之前被声明(但不会赋值)。但是如果声明变量时不使用var关键字,则变量不会被声明提前;
函数的声明提前:
使用函数声明形式创建的函数,在所有代码执行之前被创建,所以可以在函数声明前调用。使用函数表达式创建的函数,不会被声明提前,所以不能提前使用。
函数作用域:
调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁。每调用一次函数,就会创建一个新的作用域,他们之间是互相独立的。在函数作用域中,可以访问到全局作用域的变量。全局作用域中无法访问到局部作用域的变量。当在函数作用域中操作一个变量时,先在自身作用域中寻找,如果有就直接使用,如果没有就向上级作用域中寻找。
函数作用域中,也有声明提前的特性。使用var关键字声明的变量,会在函数中所有的代码执行之前被声明。函数声明也会在函数中所有的代码被执行前声明。
在函数中,不使用var声明的变量都会成为全局变量。
定义形参就相当于在函数作用域中声明了一个变量。
this:
解析器在调用函数时,每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this。this指向的是一个对象,我们称为函数执行的上下文对象。根据函数调用方式不同,this会指向不同的对象。
1.以函数形式调用,this永远都是window;
2.以方法的形式调用,this就是调用方法的那个对象。
3.当以构造函数的方式刻调用时,this就是新创建的那个对象。
使用工厂方式创建对象:
构造函数:
构造函数就是一个普通的函数,创建方式和普通函数没有区别。不同是构造函数习惯上首字母大写。
构造函数和普通函数的区别就是调用方式的不同。普通函数直接调用,而构造函数需要使用new关键字来调用。
执行流程:
1.立刻创建一个新的对象;
2.将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象。
3.逐行执行函数中的代码。
4.将新建的对象作为返回值返回。
使用同一个构造函数创建的对象称为一类对象,也将一个构造函数称为一个类。我们将通过一个构造函数创建的对象称为类的实例。
instanceof运算符:可以检查一个对象是否是一个类的实例。如:console.log(per instanceof Person);
所有的对象都是Object的后代。所以任何对象和Object做instanceof检查时,都会返回true。
原型prototype
我们创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象。
如果函数作为普通函数调用prototype没有任何作用。
当函数以构造函数形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__属性来访问该属性。
原型对象相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象。我们可以将对象中共有的内容,统一设置到原型对象中。
当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有,则直接使用; 如果没有,则会去原型对象中寻找。
以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。
使用in检查对象中是否有某个属性时,如果对象中没有但是原型中有,也会返回true。可以使用hasOwnProperty()来检查自身中是否含有该属性。
原型对象也是对象,所以它也有原型。当我们使用一个对象的属性或方法时,会先在自身中寻找,自身中如果有,则直接使用,如果没有则去原型对象中寻找,直到找到Object对象的原型。Object对象的原型没有原型,如果在Object中依然没有找到,则返回undefined。
toString():当我们直接在页面中打印一个对象时,实际上是输出的对象的toString()方法的返回值。如果我们希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法。
垃圾回收(GC):
就像人生活时间长了会产生垃圾一样,程序运行过程中也会产生垃圾,这些垃圾积攒过多以后,会导致程序运行过慢,所以需要一个垃圾回收机制,来处理程序运行过程中的垃圾。当一个对象没有任何的变量或属性对它进行引用,此时我们将永远没法继续使用,此时这种对象就像垃圾,会占用大量的内存空间,导致程序运行变慢。在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作。但是必须将对象的引用断开,如obj=null。
数组
对象分三类:内建对象、宿主对象、自定义对象
数组(Array)也是一个对象,它和我们普通的对象功能类似,也是用来存储一些值的。
不同的是普通对象是使用字符串作为属性名的,而数组是使用数字作为索引来操作元素。
索引:从0开始的整数序列。
数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据。
创建数组对象:
var arr = new Array();
//使用typeof检查一个数组时,会返回“object”
//向数组中添加元素,语法:数组[索引]=值
arr[0]=10;
arr[1]=33;
//读取元素.如果读取不存在的索引,不报错,返回“undefined”
arr[0]
使用length属性来获取数组的长度
语法: arr.length;
对于连续的数组,使用length可以获取数组元素的个数。对于非连续的数组,使用length会获取到数组最大的索引加1。
如果修改的length大于原长度,则多出部分会空出来。小于原长度的话,则截取前面的部分,多出的元素被删除。
数组遍历方法
1:for(var i=0;i<arr.length;i++){}
2.forEach()方法:此方法需要一个函数作为参数,像这种函数,由我们创建但是不由我们调用,称为回调函数。数组中有几个元素,则此函数就会执行几次。每次执行时,浏览器就会将遍历到的元素以实参的形式传递进来,我们可以定义形参,来读取这些内容。第一个参数,当前正在遍历的元素值,第二个参数为当前遍历的元素的索引; 第三个参数为当前数组。
字符串:
在底层字符串是以字符数组的形式保存的。str.length。str[0]。
length:属性,可以用来获取字符串的长度。
charAt(): 返回字符串中指定位置的字符。根据索引获取指定的字符。
charCodeAt(): 获取指定位置字符的Unicode编码。
String.fromCharCode(): 可以根据字符编码去获取字符。如String.fromCharCode(20035),得到“乃”。
concat(): 连接字符串。
indexOf(): 检索一个字符串中是否含有指定内容。返回字符串所在位置索引。
lastIndexOf():从后向前搜索字符。
slice(): 从字符串中截取字符。
substring(): 跟slice基本一样。不同的是这个方法不能接受负值,如果使用负值,则默认使用0,而且他还会自动调整参数的位置,如果第二个参数小于第一个,则自动交换参数位置。
substr():
split(): 将字符串拆分为一个数组。
ES6:
let:
1.变量不能重复声明。var可以。
2.块级作用域。ES5中有三种作用域:全局、函数、eval。
3.不存在变量提升。
4.不影响作用域链。
const定义常量:
1.一定要赋初值。
2.一般常量名使用大写(潜规则)
3.常量值不能修改。
4.块级作用域。
5.对于数组和对象的元素修改,不算做对常量的修改,不会报错。
变量的解构赋值:
1.数组的解构
const F4=['小沈阳','刘能','赵四','宋小宝']
let [xiao,liu,zhao,song] = F4;
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);
2.对象的解构:
const zhao={
name:'赵本山',
age:'不详',
xiaopin:function(){
console.log("我可以演小品")
}
}
let {name,age,xiaopin}=zhao
let {xiaopin}=zhao;
模板字符串:
ES6中引入新的声明字符串的方式 “
内容中可以直接出现换行符。
可以直接进行变量的拼接。`${变量名}是我心目中最搞笑的演员`。
对象的简化写法:
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法,这样的书写更加简洁。
方法声明的简化:
let name='尚硅谷'
let change=function(){
console.log('我们可以改变你')
}
const school={
name:name,
change:change,
improve:function(){
console.log("我们可以提高你的技能")
}
}
简写为:
const school={
name,
change,
improve(){
console.log("我们可以提高你的技能")
}
}
简头函数:
1.this是静态的,始终指向函数声明时所在作用域下的this值。
2.不能作为构造函数实例化对象。
3.不能使用arguments变量。
4.箭头函数简写:省略小括号,当形参有且只有一个的时候;当代码体只有一条语句的时候,可以省略花括号,此时return 必须省略,而且语句的执行结果就是函数的返回值。
箭头函数适合与this无关的回调,定时器,数组的方法回调。
不适合与this有关的场景,如DOM元素事件回调、对象的方法。
给函数参数赋初始值:
具有默认值的参数,一般位置要靠后(潜规则)。
默认值可以与解构赋值结合。

rest参数
ES6引入rest参数,用于获取函数的实参,用来代替arguments.arguments 是一个对象。而rest是一下纯数组。
rest参数必须放到参数最后。

扩展运算符:
“…”扩展运算符能将数组转换为逗号分隔的参数序列。

应用1:数组的合并

应用2:数组的克隆

应用3:将伪数组转为真正的数组

Symbol:

给对象添加属性和方法:
Set集合介绍与API
//声明一个set
let s = new Set();
//传入一个可迭代对象,一般为一数组。会自动去重
let s2 = new Set(['大事儿','小事儿','好事儿','坏带儿','小事儿']);
//元素个数
console.log(s2.size); //4
//添加新的元素
s2.add('喜事儿');
//删除元素
s2.delete('坏事儿');
//检测
s2.has('好事儿');
//清空
s2.clear();
//集合实现了iterator接口,帮可以使用for ...of...
//set集合实践
let arr=[1,2,3,4,6,4,3,2,1];
1.数组去重
let result=[...new Set(arr)];
2.交集
let arr2=[4,5,6,5,6];
let result=[...new Set(arr)].filter(item=>new Set(arr2).has(item));
3.并集
let union=[...new Set([...arr,...arr2])];
4.差集
let diff = [...new Set(arr)].filter(item=>!(new Set(arr2).has(item)));
Map的介绍与API
升级版的对象。
//声明
let m = new Map();
//添加元素
m.set('name','尚硅谷');
m.set('change',function(){console.log("我们可以改变你")});
let key={
school:'ATGUIGU'
};
m.set(key,['北京','上海','深圳'];
//size console.log(m.size);
//删除
m.delete('name');
//获取
m.get('change');
m.get(key);
//清空
m.clear();
//遍历
for(let v of m){
}
Class介绍与初体验
ES6的对象方法扩展
1.Object.is判断两个值是否完全相等。作用跟===很像。判断两个NaN,结果是true。
2.Object.assign对象的合并。
3.Object.setPrototypeOf设置原型对象 Object.getPrototypeof
模块化
模块化是将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
好处:1防止命名冲突; 2代码复用;3高维护性。
模块化规范产品: CommonJS(NodeJS、Browserify); AMD(requireJS);CMD(seaJS)
ES6模块化语法:
主要由两个命令构成:export和import。
暴露语法有三种:
//分别暴露
export let school='尚硅谷'
export function teach()
{
console.log("我们可以教给你开发技能")
}
let school = '尚硅谷'
function findJob()
{
console.log("我们可以帮助你找工作!")
}
//统一暴露
export {school,findJob}
//默认暴露
export default {
school:'ATGUIGU',
change: function()
{
console.log("我们可以改变你")
}
}
引入语法汇总:
<script type="module">
//引入m1.js模块内容
import * as m1 from "./m1.js"
import * as m2 from "./m1.js"
//解构赋值形式
import {school,teach} from "./m1.js"
import {school as guigu,teach} from "./m2.js" //使用别名
import {default as m3} from "./m3.js"
//简便形式,只针对默认暴露
import m3 from "./m3.js"
</script>
浏览器使用ES6模块化方式二:
创建app.js,作为入口,引入模块; 在前端html文件中只引入app.js,type认为module。
ES6模块化代码在项目中的使用:
1.安装工具:balel-cli bable_preset-env browserify(打包工具、相对简单)
//初始化
npm init --yes
//-D代表开发依赖
npm i babel-cli babel-preset-env browserify -D
//局部安装,所以用npx
npx babel src/js -d dist/js --preset=babel-preset-env
//打包
npx browserify dist/js/app.js -o dist/bundle.js
//最终在html文件中引入bundle.js即可
<script src="dist/js/bundle.js"></script>
ES6模块引入NPM包
//第一步,使用npm安装jquery
npm i jquery
//到入口文件app.js引入模块
import $ from 'jquery';
$('body').css('background','pink');
//重新转化、打包
//局部安装,所以用npx
npx babel src/js -d dist/js --preset=babel-preset-env
//打包
npx browserify dist/js/app.js -o dist/bundle.js
Promise:
Nodejs
clientHeight、clientWidth: 可见的高度、宽度,这些属性都是不带px的,返回一个数字,可以直接计算,包含内容区和内边距。属性是只读的,不可修改。
offsetWidth、offsetHeight: 获取元素的整个的宽度和高度,包括内容区、内边距和边框。
offsetParent:获取当前元素的定位父元素,会获取到离当前元素最近的开启了定位的祖先元素。如果所有的祖先元素都没有开启定位,则返回body。
offsetLeft、offsetTop: 当前元素相对于其定位父元素的水平偏移量、垂直偏移量。
scrollHeight、scrollWidth: 滚动文档的总高度、总宽度。
scrollLeft、scrollTop: 获取水平滚动条水平、垂直移动的距离。
当满足scrollHeight-scrollTop==clientHeight, 说明垂直滚动条滚动到底了。
事件对象
当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数。在事件对象中封闭了当前事件的一切信息,比如鼠标的坐标、键盘哪个按键被按下,鼠标滚轮滚动的方向。
在IE8中,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的。
使用event=event||window.event;语句解决兼容性问题。
clientX和clientY获取鼠标相对于可见窗口的X、Y坐标。
pageX和pageY获取鼠标相对于当前页面的坐标。IE8中不支持。
事件冒泡
指事件向上传导,当后代元素上的一个事件被触发时,其祖先元素的相同事件,也会被触发。
大部分情况冒泡都是有用的,如果不希望发行事件冒泡,可以通过事件对象来取消冒泡。
event.cancelBubble=true;
事件委派
BOM
BOM 浏览器对象模型,BOM可以使我们通过JS来操作浏览器。
在BOM中为我们提供了一组对象,用来完成对浏览器的操作。
BOM对象
window代表的是整个浏览器的窗口,同时window也是网页中的全局对象;
Navigator:代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
Location:代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面。History:代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录。由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时有效。
screen:代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息
JS高级之数组类型:

typeof 不能判断null与object,object与array。typeof [‘a’,’b’], 返回’object’;
undefined 与null的区别?
前者代表代表了定义了未赋值; null代表定义了并赋值了,只是值为null。
什么时候给变量赋值为null?
null的typeof返回值为object。null是基本类型。
初始值赋值为null,表明将要赋值为对象。
最后让一个指向对象的变量赋值为null,让垃圾回收器回收空间。
严格区分变量类型与数据类型
函数的prototype
1.函数的prototype属性
每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为:原型对象)。
每个对象中有一个属性constructor,它指向函数对象。
2.给原型对象添加属性(一般都是方法)
作用:函数的所有实像对象自动拥有原型中的属性(方法)
闭包的应用:定义JS模块
具有特定功能的js文件
将所有的数据和功能都封装在一个函数内部(私有的)
只向外暴露一个包含n个方法的对象或函数。
模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能。
内存溢出与内存泄露
内存溢出:一种程序运行出现的错误,当程序运行需要的内存超过了剩余的内存时,就出抛出内存溢出的错误。
内存泄露:占用的内存没有及时释放,内存泄露积累多了就容易导致内存溢出。
常见的内存泄露:意外的全局变量、没有及时清理的计时器或回调函载、闭包