问题
this指向问题
基础
var name = "小王",
age = 18;
var obj = {
name: "小张",
objAge: this.age,
myFunc: function () {
// this指向调用他的实例就是obj,obj没有age属性,所以undefined
console.log(this.name + "年龄:", this.age);
},
};
console.log(obj.objAge); //18
obj.myFunc(); // 小张年龄: undefined
var name="小王"
function showName(){
// name='张三'
// this.name先找自己showName有没有name属性,有就是张三,
// 没有就到Windows下面找 小王
console.log(this.name);
}
// showName() <==> window.showName() 所以调用实例是window
showName() //小王/张三
Foo与getName()
function Foo() {
// 普通方法
getName = function (a) {
console.log("2");
};
this.getName2 = function () {
console.log("getName2方法");
};
// 对象中的普通方法getName3无法被实例调用
getName3 = function (a) {
console.log("2");
};
return this; //通过return this,将Foo函数暴露向全局和Window一样,那么再次调用getName()就是Foo.getName()
}
Foo.getName = function (b) {
console.log("1-default");
};
Foo.prototype.getName = function (c) {
console.log("6-prototype");
};
var getName = function () {
console.log("5");
};
// 使用let后,再次定义getName就会报错SyntaxError
function getName() {
console.log("4");
}
1. Foo.getName();
静态方法 // 1-default
2.getName(); //5
var 变量提升,然后把function getName覆盖,所以返回的还是var定义的
3.Foo().getName(); //2
// Foo()函数执行后,将Foo中的所有方法提升为全局相当于this,那么Foo().getName等价于this.getName()
// Foo函数中有getName方法,虽然之前外部有getName方法,Foo中相当于重写了外部的getName方法
// 就是之前this.getName调用的是 “4”,但是Foo()调用后,Foo就变成了this,Foo()中的getName就是this的getName
4.getName(); //2
// 此刻的全局方法是Foo()中的getName()
5. new Foo.getName(); //1-default
//new 有参数列表优先于无参数列表,这里是无参数,那么先执行静态方法Foo.getName() ,加上new还是原值
6. new Foo().getName(); //6-prototype
// new后面Foo的括号代表有参数,就先执行new Foo()得到 Foo的一个实例化对象,调用实例化对象的getName没有
// Foo函数中没有this.getName方法 ,到原型中找到6-prototype
new new Foo().getName2(); //6-prototype
加个new还是new Foo().getName2();
call/apply
无参数
var name = "小王",
age = 18;
var obj = {
name: "小张",
objAge: this.age,
myFunc: function () {
// this指向调用他的实例就是obj,obj没有age属性,所以undefined
console.log(this.name + "年龄:", this.age);
},
};
var db={
name:'德玛',
age:99
}
// 使用call方法将obj中的myFunc中this指向db对象,这时在obj.myFunc中
// this.name = db.name;this.age = db.age
// obj.myFunc.call(db) //德玛年龄: 99
// obj.myFunc.apply(db) //德玛年龄: 99
有参数
var name = "小王",
age = 18;
var obj = {
name: "小张",
objAge: this.age,
myFunc: function (fm,nn) {
// this指向调用他的实例就是obj,obj没有age属性,所以undefined
console.log(this.name + "年龄:", this.age,',来自:'+fm+'去往:'+nn);
},
};
var db={
name:'德玛',
age:99
}
//传参
obj.myFunc.call(db,'武汉','北京')
// obj.myFunc.apply(db,['武汉','北京']) //德玛年龄: 99 ,来自:武汉去往:北京
是否严格模式
(function () {
var obj = { age: 18 };
function people() {
console.log(this.obj);
function student() {
obj.age++;
console.log(obj.age);
}
return student;
}
//1、undefined console.log(this.obj);
// this指向null,this.obj就是null.obj
// 2、19
// people.call()之后()调用了student,student中的obj.age就是开头的18,++ 19
people.call(null, { age: 20 })();
// 1、undefined console.log(this.obj);
// 此时this指向obj,this.obj就是obj.obj。
//2. 前面call调了obj.age++ 现在又调了一次obj.age++ 所以是20
people.apply(obj, [obj])();
})();
"use strict";
var name = "张三";
function showName() {
console.log(this.name);
}
// Cannot read property 'name' of undefined
// 严格模式下this指向是调用的对象本身。不能指向全局
showName()
es6自动严格模式,改为下面箭头函数,this就是全局
var name = "张三";
let showName = () => {
console.log(this.name);
};