首先来看一个例子:
// 1、
var obj1 = {
name: '熊大',
age: 20,
say: function() {
console.log('我是' + this.name + ',年龄' + this.age)
}
}
var obj2 = {
name: '熊二',
age: 30,
say: obj1.say
}
obj1.say() // 我是熊大,年龄20
obj2.say(). // 我是熊二,年龄30
// 2、用箭头函数
var obj1 = {
name: '熊大',
age: 20,
say: function() {
return () => {
console.log(this)
console.log('我是' + this.name + ',年龄' + this.age)
}
}
}
var obj2 = {
name: '熊二',
age: 30,
say: obj1.say()
}
obj1.say()() // obj1 // 我是熊大,年龄20
obj2.say() // obj1 // 我是熊大,年龄20
// 3、用普通函数
var obj1 = {
name: '熊大',
age: 20,
say: function() {
return function() {
console.log(this)
console.log('我是' + this.name + ',年龄' + this.age)
}
}
}
var obj2 = {
name: '熊二',
age: 30,
say: obj1.say()
}
obj1.say()() // Window // 我是,年龄undefined
obj2.say() // obj2 // 我是熊二,年龄30
首先只有在函数中才存在this指向问题
1、箭头函数,this是包裹箭头函数的那个函数的this
let obj = {
a: {
b: () => {
console.log(this)
}
}
}
obj.a.b() // window
function func() {
let obj = {
a: {
b: () => {
console.log(this)
}
}
}
obj.a.b()
}
let a = { b: 1 }
func.call(a) // a
2、普通函数
1⃣️构造函数的实例:this为构造函数的实例
2⃣️被别人点出来的函数a.myfunc(),this是调用myfunc的a
3⃣️直接调用的函数myfunc,this是window
私有上下文中的this:
- 事件绑定中,给元素的某个事件行为绑定方法,当事件行为触发,方法执行,方法中的this是当前元素本身(特殊:IE6~8中基于attachEvent()方法实现的DOM2事件绑定,事件触发,方法中的this是window而不是元素本身)
let body = document.body
body.onclick = function () {
console.log(this) // body
}
body.addEventListener('click', function () {
console.log(this) // body
})
body.attachEvent('onclick', function () {
console.log(this) // window
})
// 另一种情况:
var obj = {
show: function () {
console.log('this:', this);
}
};
body.addEventListener('click', obj.show); // body
body.addEventListener('click', obj.show.bind(obj)); // obj
body.addEventListener('click', function () { obj.show(); }); // obj
- 普通方法执行(包括自执行函数执行、普通函数执行、对象成员访问要调取方法执行等),this指向调用者。
let obj = {
fn: (function () {
console.log(this) // window
return function () {}
})()
}
function func () {
console.log(this)
}
let obj = {
func
}
func() // window
obj.func() // obj
[].slice() // 数组实例基于原型链机制,找到Array原型上的slice方法,然后再把slice方法执行,此时slice方法中的this是当前的空数组
[].prototype.slice() // 此时this是Array.prototype
- 构造函数执行(new),构造函数体中的this是当前类的实例。而原型上方法中的this不一定都是实例,主要看执行的时候,“点”前面的内容
function Func () {
this.name = 'F'
console.log(this)
}
Func.prototype.getNum = function getNum () {
console.log(this)
}
let f = new Func() // Func {name: "F"}
f.getNum() // Func {name: "F"}
Func.prototype.getNum() // {getNum: ƒ, constructor: ƒ}
- ES6中提供了Arrow Function(箭头函数):箭头函数没有自己的this,它的this是继承所在上下文中的this
let obj = {
func: function () {
console.log(this) // obj
},
sum: () => {
console.log(this) // window,块级上下文中没有自己的this
}
}
- 可以基于call/apply/bind方式,强制手动改变函数中this的指向
一些特殊情况:
window.name = 'globalName';
var myObject = {
name: 'sven',
getName: function(){
return this.name;
}
};
console.log( myObject.getName() ); // sven
window.name = 'globalName';
var myObject = {
name: 'sven',
getName: function(){
return this.name;
}
};
var getName = myObject.getName;
console.log( getName() ); // globalName
当函数不作为对象的属性被调用时,也就是我们常说的普通函数方式,此时的 this 总是指向全局对象。在浏览器的 JavaScript 里,这个全局对象是 window 对象。
当函数作为对象的方法被调用时,this 指向该对象:
var obj = {
a: 1,
getA: function(){
alert ( this === obj ); // 输出:true
alert ( this.a ); // 输出: 1
}
};
obj.getA();
hasOwnProperty
JavaScript 并没有保护 hasOwnProperty 这个属性名,因此,当某个对象可能自有一个占用该属性名的属性时,就需要使用外部的 hasOwnProperty 获得正确的结果:
var foo = {
hasOwnProperty: function() {
return false;
},
bar: 'Here be dragons'
};
foo.hasOwnProperty('bar'); // 始终返回 false
// 如果担心这种情况,
// 可以直接使用原型链上真正的 hasOwnProperty 方法
({}).hasOwnProperty.call(foo, 'bar'); // true
// 也可以使用 Object 原型上的 hasOwnProperty 属性
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
Q&A:
function a(xx) {
this.x = xx;
return this;
}
var x = a(5);
var y = a(6);
console.log(x.x); //undefined
console.log(y.x); //6
执行 x = a(5)时,函数内的this指向window,x最后也指向window,window.x=5,执行y = a(6)时,window.x=6,所以外层的x变量为6,x.x 即为 6.6 为undefined,y.x 即为 window.x 为6。
网友评论