1.在js中this是一个对象
this的值是不确定的,只有在代码运行的过程中才能确定this的值,this的值不能手动更改。
2.到处都有this
只要你可以写js代码的地方,就可以使用this
this的值是动态变化的
你可以修改this这个对象的某个属性,但不能修改this的值
3.确定this的值
1)如果this出现在普通的函数中,this表示window,如果你通过window打点调用 一个函数,这个函数中的this也是window。
<script>
function k() {
console.log(this); // window
}
window.k(); // window打点调用
k(); // 程序员自己调用
</script>
2)事件绑定,事件处理程序,事件发生时,浏览器帮我们调用这个函数,此函数中的this表示事件源
<script>
let box = document.getElementById("box");
function f(){
console.log(this); // window
return function g(){
console.log(this); // 事件源
}
}
box.onclick = f();
</script>
3)在一个对象中,如果有方法(函数),如果通过这个对象调用方法,方法中的this表示这个对象
<script>
// JS中的对象是属性的无序集合
// 属性:变量/方法
// 无序:容器中的属性没有顺序
// 集合:存放了N个数据
var wc = {
name:"dididi",
age:100,
eat:function () { // 叫方法(属性)
console.log("eat...")
console.log(this);
}
}
// 一个方法中的this是谁,就看点前面是谁。
wc.eat(); // 调用一个对象上的方法
</script>
4)在IIFE(立即调用函数)中,this表示window
<script>
(function () {
console.log(this);
})(); // 在非严格模式下,IIFE中的this表示window
</script>
5)前四点都是在非严格模式下,在严格模式下,调用一个普通函数,this表示undefined,IIFE中的this也表示undefined
<script>
"use strict"; // 启用JS的严格模式
function f() {
console.log(this); // undefined
}
f();
(function () {
console.log(this); // undefined
})();
</script>
4.更改this的值
call 改变了this指向 并 让函数执行 传递参数一个个传递
apply 改变了this指向 并 让函数执行 传送参数必须是数组
bind 改变了this指向 函数不执行
1)call
作用:更改函数内部的this的值。
call格式:
函数f.call(newObj,参数1,参数2…)
形参:
newObj:用newObj替换函数f中的this
参数1…参数n : 函数f的参数。
var abc = function (){console.log("我是:"+this.name) }
var obj1 = {name:"wc",say:abc}
var obj2 = {name:"xq",say:abc}
// 函数也是对象 对象是属性的无序集合 默认就有非常多的属性
// 其中有一个就是call
// call 的参数 对象
// 作用:
// 1)让abc中的this指向obj1 call改变this指向
// 2)让abc直接执行 调用
abc.call(obj1); // this==>obj1 abc()
abc.call(obj2);
a.利用Object.prototype.toString.call( )可以非常精确地检测一个数据的数据类型
(typof的不足:检测基本数据类型OK,对于引用数据类型来说,检测function也OK,但是其它的不OK)
<script>
console.log(typeof 1) // number
console.log(typeof "hello") // string
console.log(typeof true) // boolean
var a;
console.log(typeof a) // undefined
console.log(typeof [1,2,3]) // object
console.log(typeof {a:1}) // object
let d = new Date();
console.log(typeof d) // object
let r = new RegExp()
console.log(typeof r) // object
function f(){}
console.log(typeof f) // function
</script>
<script>
// toString() Object.prototype上面的方法
console.log(Object.prototype.toString.call(1)); // [object Number] 此时会把1瞬间包装成对象
console.log(Object.prototype.toString.call("hello")); // [object String] 此时"hello"也瞬间包装成对象了
console.log(Object.prototype.toString.call(true)) //[object Boolean]
var a;
console.log(Object.prototype.toString.call(a)) //[object Undefined]
// call 1)改变toString中的this的指向,指向了{ }
// 2)让toString执行
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
function f(){}
console.log(Object.prototype.toString.call(f)) //[object Function]
let d = new Date()
console.log(Object.prototype.toString.call(d)) //[object Date]
let r = new RegExp();
console.log(Object.prototype.toString.call(r)) //[object RegExp]
</script>
b.call应用翻转字符串
(1)循环
<script>
var str = "123456789";
var newStr = "";
for (var i=str.length-1; i>=0; i--){
newStr += str[i];
}
console.log(newStr); // 987654321
</script>
(2)借用数组
<script>
// 数组中有一个翻转的方法
var arr = [1,2,3];
console.log(arr.reverse()); // [3, 2, 1]
// 目标:让字符串翻转
// 把字符串变成数组
var str = "123456789";
console.log(str.split("")); // ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
console.log(str.split("").reverse()); // ["9", "8", "7", "6", "5", "4", "3", "2", "1"]
//console.log(str.split("").reverse().join()); // 9,8,7,6,5,4,3,2,1
console.log(str.split("").reverse().join("")); // 987654321
// 简单化:
console.log(Array.prototype.reverse.call(str.split("")).join("")); // 987654321
</script>
2)apply
apply也是用来修改function中的this。它的功能与 call是完全一样。 只是有一点不同:
它的参数列表不同:
如果函数f没有参数,则f.apply和f.call的用法是一样。
3)bind
用来更改函数内部的this。
格式:
var newf = f.bind(obj);
作用:
把函数f中的this改成obj对象,并返回一个新函数。
示例:
与call的区别:
(1)call改this,再执行函数
(2)bind改this,不执行函数,返回一个绑定新this的函数。
也可以直接在bind的后面加一个()去调用函数。