apply和call方法
作用都可以改变this的指向
没有传参数
apply和call方法中如果没有传入参数,或者传入的是null,那么调用该方法的函数的this指向是默认的window
参数
f1.apply(null, [100,200]) 数组传入参数
f1.call(null,100,200) 一个个传入
f1.apply(对象, [100,200])那么f1中的原型指向变成了 传入的这个对像
f1.call(对象,100,200)
apply和call调用的话 如果 不是写在指向原型的函数里面 相当于一次调用
并没有真正的这个对像原型里继承
运用的地方
只要想使用别的对象的方法 或者属性 运用在自己生就可以 进行调用
apply和call实际上实在 Function里面
bind方法
改变this指向
参数中没有传入对象或者null
此时的this指向默认是window
var ff = f1.bind(10, 20);
将f1复制了一份给 ff
参数可以在复制的时候传入 也可以在复制之后传
有传入对象
此时 就相当于 将f1复制一份 原型指向 per这个原型
此时 ff 就可以调用f1的属性和方法 也可以调用 per里面的属性和方法了
var ff = f1.bind(per, 10, 20);
此时只能拿到属性 不能得到方法 f1是函数
var per = new Person(10);
var stu = new Student(20);
//复制了一份
var ff1 = per.play.bind(stu);
ff1();
上面这种方式 意思就是 将per.play复制了一份 然后指向是stu
此时的参数是stu的参数为准
per.play.bind(stu)bind后面还有没有参数 是看per.play有没有参数
还有一点就是复制完 只是在 per.play这个方法里获取到stu里的参数
stu里面的参数 在 new里面进行传入
目前的调用方式
实例对象的方法 调用实例对象
函数 调用实例对象
bind的应用
parseInt()
是向下取整
function ShowRandon() {
this.number = parseInt(Math.random() * 10 + 1);
};
ShowRandon.prototype.show1 = function() {
//这里使用window全局调用了 本来this是window
//bind改变了this指向 现在this是实例对象
window.setInterval(this.show2.bind(this), 1000);
};
ShowRandon.prototype.show2 = function() {
console.log(this.number)
};
var ar = new ShowRandon();
ar.show1();
函数中的几个成员
函数中有一个那么属性 函数的名字,name属性是只读 不能修改
函数中有一个arguments属性 实参的个数
函数有一个length属性 函数定义的时候形参个数
函数中有一个caller属性 在其他函数调用这个函数 就会显示 否则为null
函数作为参数
函数作为参数,如果是命名函数,那么只传入命名函数的名字,没有括号
定时器传入函数
函数作为返回值使用
有return 可以用变量来接收
typeof 变量 判断数据类型
var obj = {};
console.log(obj instanceof Object);
获取某个对象的数据类型样子
Object.prototype.toString.call(对象)//此时得到的就是这个对象的类型
var str = "abj";
console.log(Object.prototype.toString.call(str)
排序
数组的排序 从小到大
var arr = [1, 100, 20, 200, 40, 50, 120, 10];
//排序---函数作为参数使用,匿名函数作为sort方法的参数使用,那么此时的匿名函数中有两个参数,
arr.sort(function(obj1, obj2) {
if (obj1 > obj2) {
return 1;
} else if (obj1 == obj2) {
return 0;
} else {
return -1;
}
})
console.log(arr)
1变 -1不变
数组中字符串的排序
函数作为返回值的扩展案例
排序的调用 在案例11 有详细讲解
自己做一下表格的排序
作用域和作用域链和预解析
作用域
变量 局部 全局
作用域 局部 全局
js没有块级作用域 一堆大括号中定义的变量,这个变量可以在大括号外面被使用
while(true){
// var num=10;
// break;
// }
// console.log(num);
这里是可以被访问到的
if(){
num = 10;
}
外部可以访问到
函数中定义的变量是局部变量 外部访问不到
#####作用域链
从里往外找 直到找到这个变量 没找到就是未定义
预解析
就是在浏览器解析代码之前,把变量的声明和函数的声明提前到该作用的最上面
leg
变量的提前 未定义
console,log(num);
var num = 100;
函数的提前调用
- 声明方式的函数可以被调用
f1();
function f1(){
console.log(“解决”);
}
-
函数表达式 提前调用则报错 var f2 f2()出错
原因 这个可以看作是变量 变量提前 就不会执行
f2();
var f2 = function (){
console.log(“哈哈哈”);
}
闭包
概念: 函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者数据,此时就形成了闭包 暂时不严谨
闭包模式: 函数模式的闭包 对象模式的闭包
闭包的作用: 缓存数据 延长作用域链
闭包的优点和缺点 : 缓存数据
#####函数模式的闭包 :函数中有函数
#####对象模式中的闭包: 函数中有一个对象
function f3() {
var num = 10;
var obj = {
age: num,
};
console.log(obj.age);
}
f3();
闭包的小案例
function f2() {
num = 10;
return function() {
num++;
return num;
}
}
var ff = f2();
console.log(ff());
console.log(ff());
console.log(ff());
这边有对num进行了缓存
输出 11 12 13 闭包 缓存数据
闭包模式产生相同的随机数
如果想缓存数据 ,就把这个数据放在外层函数和里层函数的中间位置
闭包的作用: 缓存数据 没有及时释放变量
局部变量在函数使用完后,就会自动的被释放
闭包 后 里面的局部变量使用作用域链就会被自动的延长
闭包案例实现点赞
function my$(tagName) {
return document.getElementsByTagName(tagName);
}
//闭包缓存
function getValue() {
var value = 1;
return function() {
value++;
//return value;
this.value = "(赞" + value + ")";
}
}
var btnObj = my$("input");
for (var i = 0; i < btnObj.length; i++) {
btnObj[i].onclick = getValue();
}
将闭包函数的返回值赋给 点击事件 相当于点击事件原本的function
沙箱
环境 黑盒 虚拟的环境 小环境 自调用函数
//沙箱---小环境
// (function () {
// var num=10;
// console.log(num);
// })();
//
// //沙箱---小环境
// (function () {
// var num=20;
// console.log(num+10);
// }());
沙箱小案例
str = str.substr(2);删掉字符串前两个
递归
函数中调用函数自己 此时就是递归 递归一定要有结束的条件
var i = 0;
function f1() {
i++;
if (i < 5) {
f1();
}
console.log("哈哈哈");
}
f1();
递归小案例
递归函数n个数字和
function getSum(x) {
if (x == 1) {
return 1;
}
return x + getSum(x - 1);
}
执行的过程如下
* 执行过程:
* 代码执行getSum(5)--->进入函数,此时的x是5,执行的是5+getSum(4),此时代码等待
* 此时5+getSum(4),代码先不进行计算,先执行getSum(4),进入函数,执行的是4+getSum(3),等待, 先执行的是getSum(3),进入函数,执行3+getSum(2),等待,先执行getSum(2),进入函数,执行 2+getSum(1);等待, 先执行getSum(1),执行的是x==1的判断,return 1,所以,
* 此时getSum(1)的结果是1,开始向外走出去
* 2+getSum(1) 此时的结果是:2+1
* 执行:
* getSum(2)---->2+1
* 3+getSum(2) 此时的结果是3+2+1
* 4+getSum(3) 此时的结果是4+3+2+1
* 5+getSum(4) 此时的结果是5+4+3+2+1
递归函数 求 一个是数字各个位数上的数字之和
//递归案例:求一个数字各个位数上的数字的和: 123 --->6 ---1+2+3
//523
function getEverySum(x) {
if (x < 10) {
return x;
}
//获取的是这个数字的个位数
return x % 10 + getEverySum(parseInt(x / 10));
}
console.log(getEverySum(1364)); //5
//递归案例:求斐波那契数列 就是 第三个数字是前两个数字之和