Web前端------JS高级apply、call、bind方法
2018-07-07 本文已影响39人
Peak_One
JS apply、call、bind方法使用介绍
在介绍apply 、call、bind方法之前很有必要做一下简单的铺垫,因为apply、call、bind方法牵涉到改变function内部this(即函数所属【或调用对象】的问题),所以将函数内部this的指向问题进行介绍:
- 函数内部this的指向
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
</head>
<body>
</body>
</html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
/*
*
* 函数中的this的指向
*
*
* 普通函数中的this是谁?-----window
* 对象.方法中的this是谁?----当前的实例对象
* 定时器方法中的this是谁?----window
* 构造函数中的this是谁?-----实例对象
* 原型对象方法中的this是谁?---实例对象
*
*
* */
//严格模式:
// "use strict";//严格模式
// function f1() {
// console.log(this);//window
// }
// f1();
//普通函数
// function f1() {
// console.log(this);
// }
// f1();
//定时器中的this
// setInterval(function () {
// console.log(this);
// },1000);
//构造函数
// function Person() {
// console.log(this);
//对象的方法
// this.sayHi=function () {
// console.log(this);
// };
// }
//原型中的方法
// Person.prototype.eat=function () {
// console.log(this);
// };
// var per=new Person();
// console.log(per);
// per.sayHi();
// per.eat();
//BOM:中顶级对象是window,浏览器中所有的东西都是window的
</script>
</head>
<body>
</body>
</html>
- 函数声明与函数表达式的区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
//函数声明
//
// if(true){
// function f1() {
// console.log("哈哈,我又变帅了");
// }
// }else{
// function f1() {
// console.log("小苏好猥琐");
// }
// }
// f1();
//函数表达式
var ff;
if(true){
ff=function () {
console.log("哈哈,我又变帅了");
};
}else{
ff=function () {
console.log("小苏好猥琐");
};
}
ff();
//函数声明如果放在if-else的语句中,在IE8的浏览器中会出现问题
//以后宁愿用函数表达式,都不用函数声明
</script>
</head>
<body>
</body>
</html>
- 拓展:数组的函数调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
//数组可以存储任何类型的数据
var arr=[
function () {
console.log("十一假期快乐");
},
function () {
console.log("十一假期开心");
}
,
function () {
console.log("十一假期健康");
}
,
function () {
console.log("十一假期安全");
},
function () {
console.log("十一假期如意");
}
];
//回调函数:函数作为参数使用
arr.forEach(function (ele) {
ele();
});
</script>
</head>
<body>
</body>
</html>
apply和call方法的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
//apply和call的使用
//作用:可以改变this的指向
// function f1(x,y) {
// console.log("结果是:"+(x+y)+this);
// return "10000";
// }
// f1(10,20);//函数的调用
//console.log("========");
//此时的f1实际上是当成对象来使用的,对象可以调用方法
//apply和call方法也是函数的调用的方式
//f1.apply();
//f1.call();
//console.log("==========");
//f1.apply(null);
//f1.call(null);
//apply和call方法中如果没有传入参数,或者是传入的是null,那么调用该方法的函数对象中的this就是默认的window
//f1.apply(null,[100,200]);
//f1.call(null,100,200);
//apply和call都可以让函数或者方法来调用,传入参数和函数自己调用的写法不一样,但是效果是一样的
// var result1=f1.apply(null,[10,20]);
// var result2=f1.call(null,10,20);
// console.log(result1);
// console.log(result2);
// function f1(x,y) {
// console.log("这个函数是window对象的一个方法:"+(x+y)+this.sex);
// }
// window.f1(10,20);
// //obj是一个对象
// var obj={
// age:10,
// sex:"男"
// };
//
// window.f1.apply(obj,[10,20]);
// window.f1.call(obj,10,20);
// console.dir(obj);
//apply和call可以改变this的指向
function Person(age,sex) {
this.age=age;
this.sex=sex;
}
//通过原型添加方法
Person.prototype.sayHi=function (x,y) {
console.log("您好啊:"+this.sex);
return 1000;
};
var per=new Person(10,"男");
per.sayHi();
console.log("==============");
function Student(name,sex) {
this.name=name;
this.sex=sex;
}
var stu=new Student("小明","人妖");
var r1=per.sayHi.apply(stu,[10,20]);
var r2=per.sayHi.call(stu,10,20);
console.log(r1);
console.log(r2);
</script>
</head>
<body>
</body>
</html>
总结:apply和call方法总结
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
//apply和call都可以改变this的指向
//函数的调用,改变this的指向
// function f1(x,y) {
// console.log((x+y)+":===>"+this);
// return "这是函数的返回值";
// }
// //apply和call调用
// var r1=f1.apply(null,[1,2]);//此时f1中的this是window
// console.log(r1);
// var r2=f1.call(null,1,2);//此时f1中的this是window
// console.log(r2);
// console.log("=============>");
// //改变this的指向
// var obj={
// sex:"男"
// };
// //本来f1函数是window对象的,但是传入obj之后,f1函数此时就是obj对象的
// var r3=f1.apply(obj,[1,2]);//此时f1中的this是obj
// console.log(r3);
// var r4=f1.call(obj,1,2);//此时f1中的this是obj
// console.log(r4);
//方法改变this的指向
// function Person(age) {
// this.age = age;
// }
// Person.prototype.sayHi = function (x, y) {
// console.log((x + y) + ":====>" + this.age);//是实例对象
// };
//
// function Student(age) {
// this.age = age;
// }
// var per = new Person(10);//实例对象
// var stu = new Student(100);//实例对象
// //sayHi方法是per实例对象的
// per.sayHi.apply(stu, [10, 20]);
// per.sayHi.call(stu, 10, 20);
//apply和call的使用方法
/*
* apply的使用语法
* 函数名字.apply(对象,[参数1,参数2,...]);
* 方法名字.apply(对象,[参数1,参数2,...]);
* call的使用语法
* 函数名字.call(对象,参数1,参数2,...);
* 方法名字.call(对象,参数1,参数2,...);
*
* 作用:改变this的指向
* 不同的地方:参数传递的方式是不一样的
*
* 只要是想使用别的对象的方法,并且希望这个方法是当前对象的,那么就可以使用apply或者是call的方法改变this的指向
*
* */
function f1() {
console.log(this+":====>调用了");
}
//f1是函数,f1也是对象
console.dir(f1);
//对象调用方法,说明,该对象中有这个方法
f1.apply();
f1.call();
console.log(f1.__proto__==Function.prototype);
//所有的函数都是Function的实例对象
console.log(Function.prototype);//ƒ () { [native code] }
console.dir(Function);
//apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype中
function Person() {
this.sayHi=function () {
console.log("您好");
};
}
Person.prototype.eat=function () {
console.log("吃");
};
var per=new Person();
per.sayHi();
per.eat();
console.dir(per);
//实例对象调用方法,方法要么在实例对象中存在,要么在原型对象中存在
</script>
</head>
<body>
</body>
</html>
bind方法的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
function f1(x, y) {
console.log((x + y) + ":=====>" + this.age);
}
//复制了一份的时候,把参数传入到了f1函数中,x===>10,y===>20,null就是this,默认就是window
//bind方法是复制的意思,参数可以在复制的时候传进去,也可以在复制之后调用的时候传入进去
//apply和call是调用的时候改变this指向
//bind方法,是赋值一份的时候,改变了this的指向
// var ff=f1.bind(null);
// ff(10,20);
// function Person() {
// this.age = 1000;
// }
// Person.prototype.eat = function () {
// console.log("这个是吃");
// };
// var per = new Person();
//
// var ff = f1.bind(per, 10, 20);
// ff();
function Person(age) {
this.age=age;
}
Person.prototype.play=function () {
console.log(this+"====>"+this.age);
};
function Student(age) {
this.age=age;
}
var per=new Person(10);
var stu=new Student(20);
//复制了一份
var ff=per.play.bind(stu);
ff();
//bind是用来复制一份
//使用的语法:
/*
* 函数名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个函数
* 方法名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个方法
*
* */
</script>
</head>
<body>
</body>
</html>
bind方法的应用小demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
//通过对象,调用方法,产生随机数
function ShowRandom() {
//1-10的随机数
this.number=parseInt(Math.random()*10+1);
}
//添加原型方法
ShowRandom.prototype.show1=function () {
//改变了定时器中的this的指向了,本来应该是window,现在是实例对象了
window.setInterval(this.show2.bind(this),1000);
};
//添加原型方法
ShowRandom.prototype.show2=function () {
//显示随机数--
console.log(this.number);
};
//实例对象
var sr=new ShowRandom();
//调用方法,输出随机数字
//调用这个方法一次,可以不停的产生随机数字
sr.show1();
</script>
</head>
<body>
</body>
</html>
函数作为参数使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
// function f1(fn) {
// console.log("f1的函数");
// fn();//此时fn当成是一个函数来使用的
// }
// //fn是参数,最后作为函数使用了,函数是可以作为参数使用
// //传入匿名函数
// f1(function () {
// console.log("我是匿名函数");
// });
// //命名函数
// function f2() {
// console.log("f2的函数");
// }
// f1(f2);
// //函数作为参数的时候,如果是命名函数,那么只传入命名函数的名字,没有括号
// function f1(fn) {
// setInterval(function () {
// console.log("定时器开始");
// fn();
// console.log("定时器结束");
// },1000);
// }
//
// f1(function () {
// console.log("好困啊,好累啊,就是想睡觉");
// });
</script>
</head>
<body>
</body>
</html>
函数作为返回值使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<script>
// function f1() {
// console.log("f1函数开始");
// return function () {
// console.log("我是函数,但是此时是作为返回值使用的");
// }
//
// }
//
// var ff=f1();
// ff();
// var num=10;
// console.log(typeof num);//获取num这个变量的数据类型
// var obj={};//对象
// //判断这个对象是不是某个类型的
// console.log(obj instanceof Object);
// //获取某个对象的数据类型的样子
// //Object.prototype.toString.call(对象);//此时得到的就是这个对象的类型的样子
//
//
//
// //此时输出的是Object的数据类型 [object Object]
// console.log(Object.prototype.toString());
// //输出的数组的数据类型 [object Array]
// console.log(Object.prototype.toString.call([]));
//
// var arr=[10,20,30];
// console.log(Object.prototype.toString.call(arr));
//
console.log(Object.prototype.toString.call(new Date()));
//获取某个对象的类型是不是你传入的类型
//[10,20,30] 是不是"[object Array]"
//type---是变量----是参数----"[object Array]"
//obj---是变量-----是参数----[10,20,30];
//判断这个对象和传入的类型是不是同一个类型
function getFunc(type) {
return function (obj) {
return Object.prototype.toString.call(obj) === type;
}
}
var ff = getFunc("[object Array]");
var result = ff([10, 20, 30]);
console.log(result);
var ff1 = getFunc("[object Object]");
var dt = new Date();
var result1 = ff1(dt);
console.log(result1);
</script>
</head>
<body>
</body>
</html>
欢迎关注我的个人微信公众号,免费送计算机各种最新视频资源!你想象不到的精彩!
0.jpg