apply和call方法:
语法分别为:
/*apply()方法*/ function.apply(thisObj[, argArray]) /*call()方法*/ function.call(thisObj[, arg1[, arg2[, [,...argN]]]]);
作用:改变this指向;
它们各自的定义:
apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。
call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。
它们的共同之处:
都“可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象”。
它们的不同之处:
apply:最多只能有两个参数——新this对象和一个数组argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里。如果argArray不是一个有效的数组或arguments对象,那么将导致一个TypeError(类型错误)。如果没有提供argArray和thisObj任何一个参数,那么Global对象将被用作thisObj,并且无法被传递任何参数。
call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表。这个方法主要用在js对象各方法相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针。如果没有提供thisObj参数,那么 Global 对象被用作thisObj。
实际上,apply和call的功能是一样的,只是传入的参数列表形式不同。
举个栗子:
function Person(age, sex) {
this.age = age;
this.sex = sex;
}
Person.prototype.sayHi = function () {
console.log("您好======" + this.sex);
}
function Student(name, sex) {
this.name = name;
this.sex = sex;
}
//先实例化人对象
var person = new Person(12, "男");
person.sayHi();
//在实例化学生对象
var stu = new Student("小明", "女");
person.sayHi.apply(stu);//结果为:您好======女
person.sayHi.call(stu);//结果为:您好======女
bind方法:
复制函数时,改变this指向,所以需要接收复制的结果,重新调用
在函数中使用:
var ff= 函数名.bind(对象,参数1,参数2...);
ff();
在对象中使用:
var ff = 实例对象.方法名.bind(对象,参数1,参数2...);
ff();
//在对象中修改this指向
function Person(age) {
this.age = age;
}
Person.prototype.sayHi = function () {
console.log("nihao-----" + this.age);
}
function Student(age) {
this.age = age;
}
//实例化人对象
var per = new Person(80);
per.sayHi();
//实例化学生对象
var stu = new Student(120);
var ff = per.sayHi.bind(stu);
console.log(per.sayHi.bind(stu));//结果为:nihao-----120
ff();
arguments: 实参的集合,是一个伪数组 caller: 调用这个方法的函数 length: 形参的个数 name: 函数的名字 function f1(x, y) { console.log(f1.arguments.length); console.log(f1.caller); } function f2() { console.log("f2的代码"); f1(1, 2); } f2(); console.dir(f1); f1(1, 2, 3);
高阶函数.....函数作为参数使用
var arr = [1, 12, 30, 4, 32];
//数组有一个方法sort排序方法----不稳定
// arr.sort();//----根据ASCII码排序
// console.log(arr);
arr.sort(function (a, b) {
if (a > b) {
return -1;
} else if (a == b) {
return 0;
} else {
return 1;
}
});
console.log(arr);
结果 /.....Array(5)0: 32 1: 30 2: 12 3: 4 4: 1 length: 5__proto__: Array(0)
函数作为返回值使用:
//需求:排序:每个文件都有名字,大小,时间,可以按照某一个属性进行排序
//创建电影对象
function File(name, size, time) {
this.name = name;
this.size = size;
this.time = time;
}
var f1 = new File("n你的名字.mp4", "400M", "2016-12-12");//n
var f2 = new File("f复仇者联盟5.mp4", "1024M", "2019-4-24");//f
var f3 = new File("b不能说的秘密.mp4", "800M", "2009-12-12");//b
var arr = [f1, f2, f3];
function getSort(attr) {
return function (obj1, obj2) {
if (obj1[attr] > obj2[attr]) {
return 1;
} else if (obj1[attr] == obj2[attr]) {
return 0;
} else {
return -1;
}
}
}
var ff = getSort("name");
arr.sort(ff);
//arr数组正序打印出来
for (var i = 0; i < arr.length; i++) {
console.log(arr[i].name + "=====" + arr[i].size + "=====" + arr[i].time);
}
结果为:
b不能说的秘密.mp4=====800M=====2009-12-12
09-函数作为返回值使用的案例.html?_ijt=f7at7ig5rf9agnor9tt2jde92v:40 f复仇者联盟5.mp4=====1024M=====2019-4-24
09-函数作为返回值使用的案例.html?_ijt=f7at7ig5rf9agnor9tt2jde92v:40 n你的名字.mp4=====400M=====2016-12-12
//预解析:把函数的声明和变量的声明提升到当前作用域的前面
console.log(num);//undefined
var num = 10;
f1();
function f1() {
console.log("燃烧我的卡路里")//燃烧我的卡路里
}
var f2;
f2();//报错
f2 = function () {
console.log(1111);
}
闭包:
函数A中,有一个函数B(对象B),函数B(对象B)可以使用函数A中定义的变量和数据,此时就形成了闭包。
闭包的模式:①函数模式的闭包,②对象模式的闭包
闭包的作用:缓存数据,延长作用域链
闭包的优点和缺点:缓存数据
function f1() {
var num = 10;
return function () {
console.log(num);//可以调用f1中的变量//10
return num;
}
}
var ff = f1();
var result = ff();
console.log("result是=====" + result);//result是=====10
function f2() {
var num1 = 100;
return {
age: num1
}
}
var obj = f2();
console.log(obj.age);//100
沙箱:
沙箱:环境,黑盒,在一个虚拟的环境中模拟真实的环境,做实验,实验的结果和真实世界一样,但是不会影响真实世界
沙箱----匿名函数的自调用
(function () {
var num = 10;
console.log(num);//10
})();
console.log(num);//undefined
var num = 100;
(function () {
var num = 1000;
console.log(num);//1000
}());
//递归:函数中调用自己本身,此时就是递归,递归一定要有结束的条件
var i = 0;
function f1() {
i++;
if (i < 5) {
f1();
}
console.log("从前有个山");
}
f1();//⑤从前有座山