# this 指向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function foo() {
console.log( this.a );
}

function doFoo() {
foo();
}

var obj = {
a: 1,
doFoo: doFoo
};

var a = 2;
obj.doFoo()
// 2

obj 调用 doFoo 方法,doFoo 中执行 foo 函数,函数调用函数则当作由 window(global)调用,所以 this 指向全局的 a=2

1
2
3
4
5
6
7
8
9
10
11
12
var a = 10
var obj = {
a: 20,
say: () => {
console.log(this.a)
}
}
obj.say()

var anotherObj = { a: 30 }
obj.say.apply(anotherObj)
// 10 10

obj 调用 say,但由于属性值为箭头函数(箭头函数没有 this),所以不能作为 obj 上的方法调用,this 指向上一层,上一层为 window,是所以输出 10
apply 可以改变函数的 this,但箭头函数无 this,所以无法改变,仍是由全局调用

1
2
3
4
5
function a() {
console.log(this);
}
a.call(null);
// window或global对象

根据 ECMAScript262 规范规定:如果第一个参数传入的对象调用者是 null 或者 undefined,call 方法将把全局对象(浏览器上是 window 对象)作为 this 的值。所以,不管传入 null 还是 undefined,其 this 都是全局对象 window 或 global。
要注意的是,在严格模式中,null 就是 null,undefined 就是 undefined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var obj = {
say: function() {
var f1 = () => {
console.log("1111", this);
}
f1();
},
pro: {
getPro:() => {
console.log(this);
}
}
}
var o = obj.say;
o();
obj.say();
obj.pro.getPro();
/*
1111 window(global)对象
1111 obj对象
{}
*/

o 在全局调用,所以 this 是 window 或 global
obj 调用 say 方法,而 say 方法中执行 fn 箭头函数,可以认为是函数调函数,但由于箭头函数无 this,指向上一层级,所以是 obj 调用,该处 this 指向 obj
不同于上,这里是 pro 调用了 getPro 这个箭头函数,这里的 this 指向上一层级 window(这里 node 中打印了空对象)(注意这里的上一层级并不是 obj)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var obj = {
foo: "bar",
func: function() {
var self = this;
console.log(this.foo);
console.log(self.foo);
(function() {
console.log(this.foo);
console.log(self.foo);
}());
}
};
obj.func();
// bar bar undefined bar

在立即执行函数中,this 指向全局(特别注意,并非有括号就是立即执行函数,(obj.func)() 本质上还是 obj.func (),this 指向还是 obj)
self 通过作用域链找到 func 中的 self,该 self 保存着 this 指向 obj

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var length = 10;
function fn() {
console.log(this.length);
}

var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
}
};

obj.method(fn, 1);
// 10 2

函数调函数,由全局调用
arguments[0]() 可以看作 arguments.fn() fn 指向 arguments

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var x = 3;
var y = 4;
var obj = {
x: 1,
y: 6,
getX: function() {
var x = 5;
return function() {
return this.x;
}();
},
getY: function() {
var y = 7;
return this.y;
}
}
console.log(obj.getX()) // 3
console.log(obj.getY()) // 6

匿名函数的 this 是指向全局对象的,所以 this 指向 window,会打印出 3;
getY 是由 obj 调用的,所以其 this 指向的是 obj 对象,会打印出 6。

1
2
3
4
5
6
7
8
9
function a(xx){
this.x = xx;
return this
};
var x = a(5);
var y = a(6);

console.log(x.x) // 6(浏览器为undefined)
console.log(y.x) // 6

return this 后,x 和 y 都是 global,global.x 就是 6
如果是在浏览器中,则代码运行顺序如下
window.x = 5 -> window.x = window -> window.x = 6 -> window.y = window
所以结果输出则为 6.x(undefined),window.x(6)

# 原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Person(name) {
this.name = name
}
var p2 = new Person('king');
console.log(p2.__proto__) //Person.prototype
console.log(p2.__proto__.__proto__) //Object.prototype
console.log(p2.__proto__.__proto__.__proto__) // null
console.log(p2.__proto__.__proto__.__proto__.__proto__)//null后面没有了,报错
console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__)//null后面没有了,报错
console.log(p2.constructor)//Person
console.log(p2.prototype)//undefined p2是实例,没有prototype属性
console.log(Person.constructor)//Function 一个空函数
console.log(Person.prototype)//打印出Person.prototype这个对象里所有的方法和属性
console.log(Person.prototype.constructor)//Person
console.log(Person.prototype.__proto__)// Object.prototype
console.log(Person.__proto__) //Function.prototype
console.log(Function.prototype.__proto__)//Object.prototype
console.log(Function.__proto__)//Function.prototype
console.log(Object.__proto__)//Function.prototype
console.log(Object.prototype.__proto__)//null

原型入门

1
2
3
4
5
6
7
8
9
function changeObjProperty(o) {
o.name = "baidu"
o = new Object()
o.name = "byte"
}
let company = new Object();
changeObjProperty(company);
console.log(company.name);

输出为 baidu,传入参数为 company,则此时变量 o 引用的是 company,可以直接对对象进行操作,如果此时重新赋值 new Object,那么此时 o 指向新建的对象,此时 o 再进行的操作都与 company 无关

1
2
3
4
5
function Person() {}
function Father() {}
Father.prototype = new Person()
const son = new Father()

指向 Person,虽然在原型链上,但原型继承无法继承构造函数

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

EvilMoOd 微信支付

微信支付

EvilMoOd 支付宝

支付宝