this的指向问题
1.this指向被不经意改变的场景
this的指向为沿着原型链查找调用此函数的对象,其具有动态性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<button id='test'>按钮</button>
<script type="text/javascript">
window.id = "window";
document.querySelector('#test').onclick = function () {
console.log(this)//<button id='test'>按钮</button>
console.log(this.id);//test
var fun = function () {
console.log(this.id);
}
// fun();//window
fun.apply(this)//test
fun.call(this)//test
}
</script>
</body>
</html>
另一法:
window.id="window";
document.querySelector('#test').onclick = function(){
var that = this;
console.log(this.id);//test
var fun = function(){
console.log(that.id);
}
fun();//test
}
因此如何将当前函数、变量绑定为当前对象?上面总结为两种方法:apply
、call
、var that=this
2.深入call、apply
使用apply或call调用,两种方法均会改变this的指向。每个函数都包含两个非继承而来的方法:call()方法和apply()方法。
apply :第一个参数:函数体内this的指向,第二个参数:接收一个集合对象(数组和类数组)
call:第一个参数L函数体内的this指向,第二个参数往后是依次传入的参数
//例一
function add(c, d) {
return this.a + this.b + c + d;
}
var s = { a: 1, b: 2 };
console.log(add.call(s, [3, 4])); // 33 原因:1+2+[3,4]+undifined=3+[3,4]+undifined=33
console.log(add.call(s, 3, 4)); // 1+2+3+4 = 10
console.log(add.apply(s, [5, 6])); // 1+2+5+6 = 14
//例二
window.firstName = "Cynthia";
window.lastName = "_xie";
var myObject = {firstName:'my', lastName:'Object'};
function getName(){
console.log(this.firstName + this.lastName);
}
function getMessage(sex,age){
console.log(this.firstName + this.lastName + " 性别: " + sex + " age: " + age );
}
getName.call(window); // Cynthia_xie
getName.call(myObject); // myObject
getName.apply(window); // Cynthia_xie
getName.apply(myObject);// myObject
getMessage.call(window,"女",21); //Cynthia_xie 性别: 女 age: 21
getMessage.apply(window,["女",21]); // Cynthia_xie 性别: 女 age: 21
getMessage.call(myObject,"未知",22); //myObject 性别: 未知 age: 22
getMessage.apply(myObject,["未知",22]); // myObject 性别: 未知 age: 22
3.call和apply其他使用方法
类数组
这里把符合以下条件的对象称为类数组
1.具有length属性
2.按索引方式存储数据
3.不具有数组的push,pop等方法
3.1实现两个数组合并
var arr1=new Array("1","2","3");
var arr2=new Array("4","5","6");
Array.prototype.push.apply(arr1,arr2);
console.log(arr1);//["1", "2", "3", "4", "5", "6"]
3.2实现类数组中的最大值
(function(){
var maxNum = Math.max.apply(null,arguments);
console.log(maxNum);//56
})(34,2,56);
3.3判断数据类型
console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]