在 ES6 之前,函数内部 this 的指向是由该函数的调用方式来决定的
函数调用方式
使用函数调用方式调用函数时,函数内部的 this 指向 window 对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</style>
</style>
</head>
<body>
<script>
var name = 'Tom';
function fn() {
console.log(this.name);
}
// Tom
fn();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</style>
</style>
</head>
<body>
<script>
var age = 18;
var Person = {
age:15,
say:function() {
console.log(this.age);
}
}
var f = Person.say;
// 18
f();
</script>
</body>
</html>
方法调用方式
使用方法调用方式调用函数时,函数内部的 this 指向调用该函数的对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="box">
<img src="photo.jpg" alt="" />
<span class="tag">标签<i></i></span>
</div>
<script>
function Person() {
this.name = 'Tom';
}
Person.prototype.run = function() {
console.log(this.name);
}
var p = new Person();
// Tom,this 指向调用该函数的对象 p
p.run();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="box">
<img src="photo.jpg" alt="" />
<span class="tag">标签<i></i></span>
</div>
<script>
var length = 50;
var getLength = function() {
console.log(this.length);
}
var t = {g:getLength, length:100};
// 100,this 指向调用该函数的对象 t
t.g();
</script>
</body>
</html>
构造函数调用方式
使用构造函数调用方式调用函数时,函数内部的 this 指向调用该函数的实例对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</style>
</style>
</head>
<body>
<script>
function Person() {
this.name = 'Tom';
}
Person.prototype.say = function() {
console.log(this.name);
}
var p = new Person();
// Tom,this 指向实例对象 p
p.say();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</style>
</style>
</head>
<body>
<script>
function Jquery() {
var _init = Jquery.prototype.init;
var o = new _init();
return o;
}
Jquery.prototype = {
constructor:Jquery,
length:100,
init:function() {
// 1. 首先查看本身有没有 length 属性
// 2. 如果没有,则去它的原型对象中查找
// 3. 如果原型对象中没有,则去它的原型对象的原型对象中查找,最终一直找到根对象(Object.prototype)
// 4. 最终没有找到的话,则表示该对象中没有该属性,获取一个对象中某个不存在的属性时,该属性的值为 undefined
console.log(this.length);
}
}
// 输出:undefined
Jquery();
</script>
</body>
</html>
上下文调用方式
- call 方法和 apply 方法的第一个参数决定了函数内部 this 的指向
1)如果第一参数是对象类型,那么函数内部的 this 指向该对象
2)如果第一参数是 null、undefined,那么函数内部的 this 指向 window 对象
3)如果第一参数是数字,那么函数内部的 this 指向 Number 构造函数的实例
4)如果第一参数是字符串,那么函数内部的 this 指向 String 构造函数的实例
5)如果第一参数是布尔值,那么函数内部的 this 指向 Boolean 构造函数的实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</style>
</style>
</head>
<body>
<script>
function fn() {
console.log(this);
}
// (3) [1, 3, 5]
fn.call([1, 3, 5]);
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
fn.call(null);
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
fn.call(undefined);
// Number {1}
fn.call(1);
// String {"abc"}
fn.call("abc");
// Boolean {true}
fn.call(true);
// (3) [1, 3, 5]
fn.apply([1, 3, 5]);
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
fn.apply(null);
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
fn.apply(undefined);
// Number {1}
fn.apply(1);
// String {"abc"}
fn.apply("abc");
// Boolean {true}
fn.apply(true);
</script>
</body>
</html>
call 方法和 apply 方法的不同之处:传参的形式不同
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</style>
</style>
</head>
<body>
<script>
function getString(a, b, c) {
console.log(a+" "+b +" "+c);
}
// 1 3 5
getString.call(null, 1, 3, 5);
// 1 3 5
getString.apply(null, [1, 3, 5]);
</script>
</body>
</html>
- bind 方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</style>
</style>
</head>
<body>
<script>
var obj1 = {
age:18,
run:function() {
setTimeout(function() {
console.log(this.age);
}, 50);
}
}
// setTimeout 是由 window 调用的,所以输出 undefined
obj1.run();
var obj2 = {
age:18,
run:function() {
setTimeout((function() {
console.log(this.age);
}).bind(this), 50);
}
}
// 通过执行bind方法,将匿名函数内部 this 指向 obj2 对象,所以输出 18
obj2.run();
function speed() {
console.log(this.seconds);
}
// 通过执行bind方法,将 speed 函数内部 this 指向 {seconds:100} 对象
var speedBind = speed.bind({seconds:100});
// 100
speedBind();
// 以上代码通常优化为:
(function speed() {
console.log(this.seconds);
}).bind({seconds:100})();
</script>
</body>
</html>
网友评论