工作中经常被this坑,虽然解决了但一直没有去整理,现在集中整理下自己对this的理解,也是百度了很久,看了很多大神的写的,都很详细,自己整理一下,加深对this的印象吧。
之前看到一句话this用通俗一点的话来讲就是谁调用它,它就指向谁,说的好像没毛病。
但是还是要分细一点:this的指向
在没有任何任何操作下,this是指向全局的即window。
1:在作为对象的方法被调用时:this指向该对象
window.name = "cheng000";
var obj = {
name:"cheng",
getname:function () {
console.log(this.name)
}
};
obj.getname();//cheng
2:作为普通函数调用:this是指向全局的即window;
var getName0 = obj.getname;
getName0();//"cheng000"
这个例子可以和document.getElementById结合着想
var el=document.getElementById(‘div’)和var getId = document.getElementById;getId (‘div’)是不一样的,前者函数内部的this指向是document,后者是指向window
或者:
var getName = function () {
var name = "cheng1";
return this.name;
}
console.log(getName()) // chengcan000不是cheng
或者:
obj.getname1 = function(){
function newgetname () {
console.log(this.name)
}
newgetname()
}
obj.getname1()
所以不管this在哪里,只要是作为普通函数或者独立函数来调用,就是指向window,
3:构造器的使用:构造函数 this就是指向返回的这个的对象
var person = function(){
this.name="ch";
this.getName=function () {
return this.name;
}
}
var person1 = new person();
console.log(person1.getName())//ch
4:结合Function.prototype.call或者是apply调用可以改变this指向
var obj2 = {
name:"cheng2",
}
obj.getname.call(obj2)
这里用到了call,call和apply是给function定义的两个方法:Function.prototype.call和apply,call和apply基本上是一样的,它们的第一个参数是指定了体内this的指向,call后面的参数是传的动态的参数,apply就只有一个参数,这个参数就是所有动态的参数集合的一个数组;
上述的第四种用法就是call和apply的用途之一,
还有就是继承,就用apply做例子吧
function dd (name,age,sex) {
this.name=name;
this.age=age;
this.sex=sex;
this.showsex=function () {
console.log(this.sex)
};
this.showage=function () {
console.log(this.age)
};
};
dd.prototype.showage1 = function () {
console.log(this.age)
}
function cc (name1,arry) {
this.name1 = name1;
this.showname=function () {
console.log(this.name+"今年"+this.age+"性别:"+this.sex+this.name1)
};
dd.apply(this,arry)//call前面为父级,括号里面为子元素;子能获取父元素的内容,父级不能用子,这里的参数arry是cc这个构造函数的参数传过来的,我看的时候完全晕在这里了,还好我足够努力。
};
var me=new cc('xiaobai',['xiaohong',18,'men']);
me.showname();、//xiaohong今年18性别:menxiaobai cc能用bb里面的方法
me.showsex(); //men
me.showage(); //18
me.showage1(); //继承只能继承实例,而不能继承原型
说道apply,有一个很有用的方法两个数组的叠加,当然你用concat()也可以,但是会增加一个新的数组,
var new1arr = [1];
var new2arr = [2,3];
console.log(new1arr.concat(new2arr))
Array.prototype.push.apply(new1arr,new2arr);
console.log(new1arr)//[1,2,3]
还有一种
for(var i in new2arr){
new1arr.push(new2arr[i]);
}
但是看上去比较麻烦,对于程序员还是越少代码越好,是吧,既然说到了原型就说下吧
原型:在js中每当定义一个函数数据类型(普通函数,类)时候,都会自带一个prototype属性,这个属性指向原型对象,原型对象是共有的,每一个实例都能够访问
function Person(name) {
this.name = name;
}
Person.prototype.getName = function () {
console.log(this.name)
}
var person1 = new Person('xiaohong');
person1.getName()
console.log(Person.prototype==person1.__proto__)//true
console.log(Person.prototype.constructor==Person)//true
原型链:每一个数据类型(普通的对象,实例,prototype)都有__proto__,数据类型(实例)的—__proto__的指向Person的prototype。constructor是prototype的一个属性,他又指回函数。每当你new一个对象的时候,实际上经历了person1-Person-Object这样的就会形成链。可以看出Object是原型链的顶端,任何对象的原型链最终都会指向Object的原型。在网上找到一张图,很清楚的带你了解原型链