第一天
1.面向对象和面向过程
-
面向过程:作为一个执行者,关注是过程中每一步,事事亲力亲为。
-
面向对象:作为一个指挥者,关注的是对象能干什么,需要什么对象
-
注意:对于 对象 本身,对象内部还是过程
2.面向对象编程
明确需求→划分对象→对象分工→对象合作→完成目标
3.对象与类
对象,具体的实例,也叫实例对象。
-
属性:静态特征
-
方法:功能特征。方法要赋值为函数。
4.new关键字的执行过程
执行过程: var zs = new Obj('zs',18)
-
向内存申请一块空间,存放对象
-
进入构造函数内部,让this(搬运工)指向当前创建的对象(当前申请的空间)
-
通过this.key = value方式,向堆中搬运属性和方法。
-
变量在栈中开辟空间,进行赋值运算此时this指向变量
-
new关键字执行完毕,会把内存的地址返回给变量名。
5.认识原型
为什么学习原型?
前提:当创建对象时,如果对象的属性变化,方法不变,在创建多个对象时就会添加很多方法,占用内存
解决:将不变的方法提出来共享
-
原型就是一个对象,系统为函数自动分配的。
-
原型中自带一个constructor指向相关的函数
-
-
获取原型: ==构造函数名.prototype==
-
使用方式:==原型对象.方法名= function(){ // 执行程序 }==
-
作用:放在原型中的方法,可以被相关构造函数创建的实例对象==共享==
-
实例对象在去调用一个属性或方法时,查找的过程是这样的:
-
先从实例对象自身中查找,若查找不到
-
则会通过系统给
__proto__
存放的原型地址,进入原型中查找
-
-
构造函数和原型的关系:
-
构造函数可以通过prototype获取原型
-
原型可以通过constructor获取构造函数
-
6.原型链
-
本质:就是实例对象调用属性或方法的过程
-
原型链过程是这样的:
-
先从实例对象自身中查找,若查找不到
-
则会通过系统给
__proto__
存放的原型地址,进入原型中查找,若原型中查找不到 -
则原型会通过
___proto__
会去原型的原型中查找,以此类推Object 是构造函数 Object 的原型: Object.prototype Object是祖宗类 原因:所有的对象,不论是任何类型,都属于Object 终于明白万物皆对象
-
第二天
1.继承
-
继承:子类和父类的关系
-
作用:减少代码冗余
2.原型继承
-
如何实现原型继承?
-
更改子类的prototype指向父类的一个具体实例。
子类.prorotype= new 父类()
,原型指向新的对象,可以使用它的属性,调用新原型的方法,以及新原型的原型中的方法 -
在新的原型上添加constructor指向子类。
子类.prorotype.constructor=子类
-
-
优缺点:
-
// 优点:完美的继承了方法
-
// 缺点:无法完美的继承属性,当属性需要变化时无法达到要求
-
3.借用继承
call方法的使用
-
目的:借用其他函数中的操作
-
实现方式:更改函数内部this的指向
-
语法:
函数名.call(借用者,实参,实参...)
-
如何实现借用继承?
-
在子类构造函数中,通过call方法调用了父类构造函数、
-
实现方式: 父类.call(this子对象的地址,实参...)
-
-
优缺点:
-
优点:可以完美的继承属性
-
缺点:无法继承方法
-
apply方法的使用
函数名.apply(借用者,[实参....]) (与call使用方法一样,区别在于实参需要放入数组中)
bind方法的使用
-
语法:函数名.bind(借用者,实参....)
-
作用:不会立刻执行,返回一个新的函数,需要调用新的函数
fn.bind(obj,10,20)(); 函数需要调用一下,效果与call,apply一样
伪数组借用数组中方法
Array.prototype.push.call(obj,xx);
var r = Math.max.apply(arr,arr); 借用math对象中的方法取出数组最大值
4.组合继承
原型+借用
-
过程:
-
原型继承弥补了借用继承无法继承方法的缺点。
-
借用继承弥补了原型继承无法完美继承属性的缺点。
-
-
缺点:在原型链中会有多余属性
第三天
1.函数作为函数的参数-回调函数
常见的语法格式:
-
function 函数名(v){ v() }
-
function 函数名(v){ v(实参,实参) }
-
原理:
-
实参和形参的关系,实参赋值给了形参
-
-
实际应用场景:当一个函数内部,需要接受外部传入一段程序时,使用回调函数
2.函数作为函数的返回值
-
语法格式:
-
function 函数名(){ return function(){ // 执行代码 }; }
-
function 函数名(){ var i = function(){ // 执行代码 }; return i }
-
-
原理:利用了return谷关键字。 return 数据
-
应用场景:在闭包中会应用
闭包
闭包是将函数内部和函数外部连接起来的桥梁
总结:
-
变量的生命周期:变量在内存中的创建和销毁
-
全局变量:何时生→打开程序时, 何时销毁→关闭程序
-
局部变量:何时生→调用函数时, 何时销毁→函数调用执行结束后
-
-
GC:全称Garbage Collection
-
垃圾回收机制,回收和销毁没有用的数据。
-
没有用的数据,不在使用的数据。
-
-
闭包:函数内部的子函数,桥梁
-
作用:
-
延长局部变量的生命周期
-
维护局部变量的安全
-
-
如何检测一个程序是否存在闭包:
-
调试:在子函数内部设置断点,刷新检测,右侧是否存在closure
-
规则:
-
外层函数 和 子函数
2. 外层函数必须有局部变量
3. 子函数要操作外层函数的局部变量
-
让子函数和外部产生关联。
-
-
function xp(){
var a = 10;
function dp () {
console.log(a)
}
return dp;
}
var bs = xp();
bs();
外部调用子函数,子函数调用外层函数局部变量,产生闭包
js中函数中的参数是局部变量,在函数的内部可以使用,函数外部不可以
闭包经典案例
在页面上有一组元素(如按钮),点击哪个元素就显示哪个元素的索引
var btns = document.querySelectorAll('button');
for (var i = 0; i < btns.length; i++) {
(function (i) {
// var i; 局部变量 产生函数嵌套,参数就是局部变量,内层函数使用外层函数变量
btns[i].onclick = function () {
alert(i);
}
})(i);
}