一,出现this的地方
1. 什么是this?
函数运行的主体,谁运行这个函数,this就是谁,分严格模式和非严格模式, 严格模式下window都为undefined,反之window对象
2. this作用
this提供了一种简明的方式来隐式传递一个对象引用,可以让函数接口设计的简单且容易复用
3. 什么出现this
this是在运行时绑定,而不是在编写时绑定,this实际值取决于函数调用时的上下文。this的绑定和函数声明的位置没有关系,只取决于函数的调用方式。在JavaScript中,当函数被调用时,会创建一个活动记录(执行时上下文),这个记录包含函数在何处调用、函数的调用方法和传入参数等信息,this会记录其中一个属性。判断this实际绑定值,关键在于分析函数实际调用的位置。
ES6打破了这种局面,在定义的时候已经定义好了this
4. 如何修改this指向
- call/apply/bind第一个参数
call/apply的区别?
call单个传值,apply已数组打包的方式传值 => fn.call(obj, 1,2,3) fn.apply(obj, [1,2,3]);
bind:预处理,事先处理好了,事件常用 IE6 ~ IE8不兼容
eg: oDiv.onclick = function() {}.bind(this)
模拟call
capply和apply用途, 快速求数组最值
Array.prototype.getMax = function() {
return Math.max.apply(this, this);
};
Array.prototype.getMix = function() {
return Math.min.apply(this, this);
};
- 将当前this赋值给一个对象,存储下来, 作用域链去机制去查找, var _this = this; jQ常用 var $that = $(this);
- new 类() 改变函数里面的this为当前类的实例, 不加new是window对象,在非严格模式下,严格模式下undefined
=>new 一个类执行四部曲:
1. 私有作用域预解释(带var和function的分别进行声明和定义)
2. 隐式创建一个新对象 ( let obj = {} )
3. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
4. 执行构造函数中的代码(为这个新对象添加属性) this.xxx = xxx;
5. 隐式返回新对象 return obj;
注意: 如果自己写return的话, 基本数据类型不受影响,如果返回引用数据类型,会把this对象给覆盖了
- es6 箭头函数 (arrow function) => 定义的时候已经完成了
5. 总结this出现的情况
- 自执行函数中的this(自执行函数) ==>window
- 函数执行返回函数中的this ==>匿名函数是window
- 对象中的this ==> 这个对象,对象的方法用箭头函数是window
- 普通函数执行的两种情况(前面有没有点<.>) ===>有点,this就是前面的,没有就是window
- 给DOM元素绑定事件中的this ==> DOM元素
- call/apply中的this ==>> params1参数
- bind中的this 在类的构造函数中 oDiv.onclick = function() {this.num =1}.bind(this);
- 定时器和超时器中的this(setInterval/setTimeout) ==> window
- *回调函数中的this(callback), ==> window
- 构造函数中的this(new Class) ==> 类的某个实例
- *ES6中箭头函数中的this ==> 上级作用域里面的this
- 当前作用域里面没有this,上级作用域里的this,上级没有在上级,直到window为止
- 在Node里面没有this,都是模块
- 1.箭头函数里面没有this,上级this,解决定时器,赋值问题(函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。) **this对象的指向是可变的,但是在箭头函数中,它是固定**
- 2.箭头函数不能用类,不能new ,因为没有constructor,和原型prototype
- 3.箭头函数没有arguments,用reset代替
- 4.不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
ES5中的this是在函数运行时候定义的 (跟在哪没有关系,执行环境有关系)
ES6中的箭头函数this是在代码解释的时候已经定义好了(跟在哪环境有关系)
6. this情况详解
eg1:自执行函数中的this(自执行函数)
什么是自执行函数? 声明完毕立即执行
格式如下:
;(function(){}());
;(function(){})();
;~function(){}()
;!function(){}()
;(function(){
console.log(this); // this==> Window
}());
const tools = function(){
console.log(this); // this==> Window
}();
const jQuery = function() {
var jQuery = function(select, context) {
};
this.jQuery = this.$ = jQuery; // ==>> window.jQuery = window.$ = jQuery;
}();
eg2:函数执行返回函数中的this(函数执行前面没有点,非严格模式下是window,严格模式下是undefined,有点的话,点前面是什么,this就是什么)
var x = 1;
var fn = function() {
var x = 100;
return function() {
console.log(this.x); // this ==> Window
};
};
fn()(); // ==> 1
eg3:对象中的this
var x =1;
var obj = {
x: 100,
fn() {
console.log(this.x); //this ==> obj
},
getX(){
return function() {
console.log(this.x); // this ==>
}
}
};
obj.fn(); //==> 100
obj.getX()(); //==> 1 函数执行返回一个匿名函数,没有执行主体,默认是window
eg2:
function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 2
eg4:普通函数执行的两种情况(前面有没有点<.>) (隐式绑定)
var x = 1;
var fn = function() {
console.log(this.x); // this ==> Window this==>> obj
};
var obj = {
name: 100,
fn:fn, //*** ===>> 隐式绑定
getX(){
return function() {
return fn;
}
}
};
fn(); // ==> 1
obj.fn(); // ==> 100
obj.getX()()(); // ==> 1
eg5: 给DOM元素绑定事件中的this
var fn = function() {
console.log(this); // this ==>> Window
};
var oDiv = document.getElementById('div1');
oDiv.onclick = function() {
console.log(this); // this ==>> oDiv
fn();
};
eg6: call/apply中的this(强行该变this指向),严格模式下是undefined
fn.call/apply(this的代替, params);
var x =1;
var obj = {
x: 100,
fn() {
console.log(this.x); //this ==> obj
},
getX(){
return function() {
console.log(this.x); // this ==>
}
}
};
obj.fn.call(obj);
obj.getX.apply(obj)()();
用途:
数组快速求最值问题
Array.prototype.getMax = function() {
return Math.max.apply(null, this);
};
Array.prototype.getMin = function() {
return Math.min.apply(null, this);
};
eg7: bind中的this
var oSpan = document.getElementById('span1');
待续
oDiv.onclick = function() {
csonole.log(this);
}.bind(oSpan);
eg8:定时器和超时器中的this(setInterval/setTimeout)
==>>eg1:
setTimeout(function(){
console.log(this); // this==> Window
}, 1000);
==>>eg2:
var x = 1;
setInterval(function(){
var x = 100;
console.log(this.x); //this==> Window 1
}, 1000);
==>>eg3: 这里出了问题,this是window,所以我们常常 var _this = this;
oDiv.onclick = function() {
setTimeout(fucntion(){
this.innerHTML = '嘿嘿~~~';
}, 1000);
};
解决办法:
1) 存储当前this
2) ES6箭头函数
oDiv.onclick = function() {
//==>ES5存储this解决
var _this = this;
setTimeout(fucntion(){
_this.innerHTML = '嘿嘿~~~';
}, 1000);
//==>ES6箭头函数解决
setTimeout(() =>{
this.innerHTML = '嘿嘿~~~';
});
};
eg9: 回调函数中的this(callback) (***)
什么是回调函数: 当一件事情做完去做另一件事情
回调函数的演进:
--- callbapck
--- promise
--- Generator
--- async awit
var x = 1;
function fn(callback) {
var x = 100;
setTimeout(function(){
callback(x);
callback(this.x);
}, 500);
}
fn(function(val){
console.log(val); ??多少呢
});
eg10: 构造函数中的this(new Class) ==>>实例
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = function() {
console.log(this.name);
};
Person.getAge = function() {
console.log(this.age);
};
// ***==>>不使用new的情况, 他就是普通函数
1. 函数执行
2. 形参赋值
3. 预解释
4. 代码从上到下执行
5.执行完毕,返回值
6.看外面有接收没有,没有内存释放,有了占用内存,不释放,需要手动释放
var person1 = Person('常连海', 26);
查看person1是什么?
console.dir(person1); //==> undefined 因为函数没有return,默认返回undefined
//一下俊报错 undefined
person1.name;
person1.age;
person1.getAge;
//***==>> 使用new的情况,角色变量,成了一个类,有原型,私有属性等等
1.函数执行
2.浏览器默认创建一个这个类的实例(this)
3.代码从上到下执行, this.xxx = xxx; 给这个实例挂属性和方法
4.return this; 返回这个实例,
5.看外面有接收没有,没有内存释放,有了占用内存,不释放,需要手动释放
注:
1)当使用类的时候,不传参数可以去掉括号
2)一般类名首字母大写,区分
3)不能手动加return,基本数据类型不印象,引用数据类型会把实例覆盖了(funciton/object)
var person = new Person('clh', 25);
console.dir(person);
person.name;
person.age;
person instanceof Person;
person.getName();
Person.getX();
eg11: ES6中箭头函数中的this(ES6箭头函数中是没有this,他的this是上级作用域里面的this,作用链问题)
==> ES6中引入了箭头函数,箭头函数使用操作符=>定义。箭头函数不使用上面4种this绑定规则,而是根据外层作用域来决定this:
==>> 1.箭头函数没有this (上级作用域里面的this)
==>> 2.箭头函数没有arguments对象 (reset参数代替)
eg1:
;(() => {})(
console.log(this); // this ==> Window
);
eg2:
var name = 'Jon';
var obj = {
name: 'LiHua',
getName:()=> {
console.log(this.name);
}
};
obj.getName();
obj.getName.call(obj);
eg3:
oDiv.onclick = function() {
setTimeout(()=>{
this.innerHTML = 'hellow world';
});
};
eg12.箭头函数
let name = 'vue';
let obj = {
name: 'es6',
showName1: ()=>{
console.log(this.name);
},
showName2() {
console.log(this.name);
},
showName3() {
setTimeout(() =>{
console.log(this.name);
});
},
showName4: function(){
return () => {
console.log(this.name);
}
}
};
obj.showName1(); // ==> ''
obj.showName2(); //==> es6
obj.showName3(); //==> es6
obj.showName4()(); // ==> es6
7. 面试提关于this的总结
eg1: 基础
var name = 1;
function a() {
var name = 2;
console.log(this.name);
console.log('inner' + this);
}
a();
console.log('outer' + this);
eg2: 加深
var name = "windowsName";
var a = {
name: "Cherry",
fn: function () {
console.log(this.name); // Cherry
}
}
a.fn();
window.a.fn();
eg3. 引出函数
var name = "windowsName";
var a = {
name: null,
// name: "Cherry",
fn: function () {
console.log(this.name); // windowsName
}
}
var f = a.fn;
f();
eg4. 内部this
var name = "windowsName";
function fn() {
var name = 'Cherry';
innerFunction();
function innerFunction() {
console.log(this.name); // windowsName
}
}
fn()
eg5. 箭头函数
var name = "windowsName";
var a = {
name: "Cherry",
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout(() => {
this.func1()
}, 100);
}
};
a.func2() // Cherry
…