JS大坑之一this关键字

var name = "clever coder";
var person = {
 name : "foocoder",
 hello : function(sth){
  console.log(this.name + " says " + sth);
 }
}
person.hello("hello world");

以前学过java,看到JavaScript的的内容的时候翻了两页,直接就跳过了,今天开始学Ajax重构的时候,才发现原来JavaScript有这么多不同,比如今天踩的坑this关键字。

首先我们要清楚几个概念——变量和属性。

有些书说的其实是不正确的,变量和属性是两个概念,我们来引用一个例子

var a =5;
b = 4;  // equal to windows.b = 4
alert(delete a); // false
alert(delete b); // true
第一个a我们用var声明了,就是变量,而第二个没有就是属性而且是个全局属性,在浏览器意思就是为windows添加一个属性b,为它赋值4,接下来继续看alert的弹窗,第一个弹出false,第二个弹出true,因为 变量是无法被删除的,而属性可以

继续。

this关键字在global code中的指的是全局对象,在浏览器就是指windows对象

alert(this)
//window
this单纯在函数中使用
function fooCoder(x) {
 this.x = x;
}
fooCoder(2);
alert(x);// 全局变量x值为2
alert(delete x);//弹出true

在这里,this指的也是Windows对象,以上代码可以在chrome开发者工具(F12)的控制台直接运行,并且查看相关参数,我们可以看到这里也是弹出的全局属性x,且因为是属性所以可以被删除,弹出的窗口是true。

this作为对象方法调用

var name = "clever coder";
var person = {
 name : "foocoder",
 hello : function(sth){
  console.log(this.name + " says " + sth);
 }
}
person.hello("hello world");
输出 foocoder says hello world。this指向person对象,即当前对象。这里有一个js对象的概念,如下

var person={firstname:"Bill", lastname:"Gates", id:5566};

其中person是对象,大括号里面的firstname是属性名,"Bill"是属性值。逗号分隔开每个属性,最后不能以分号结尾,具体请参阅w3school相关资料。之所以提出这个是为了不跟下面this在内部函数的用法混淆:

代码如下

var name = "clever coder";
var person = {
 name : "foocoder",
 hello : function(sth){
  var sayhello = function(sth) {
   console.log(this.name + " says " + sth);
  };
  sayhello(sth);
 }
}
person.hello("hello world");
//clever coder says hello world
这个代码块上面的那个代码块的最里面的function是作为一个叫hello的 方法,这个方法归属于person对象,所以方法里面的this指的是person对象。而现在这个内部函数你看清楚,hello方法里面又声明了一个叫sayhello的 函数,注意这里是等号,所以这就是容易混淆的地方。sayhello是一个函数块,并不是一个方法,而函数块默认里面的this是全局windows。

所以一般这个this如果你想绑定到person上就要用一个变量保存this先,例如取名that或者self

var name = "clever coder";
var person = {
 name : "foocoder",
 hello : function(sth){
  var that = this;
  var sayhello = function(sth) {
   console.log(that.name + " says " + sth);
  };
  sayhello(sth);
 }
}
person.hello("hello world");
//foocoder says hello world
this作为构造函数时
new FooCoder();
函数内部的this指向新创建的对象。

apply 和 call 调用以及 bind 绑定:指向绑定的对象:

var myObject = {value: 100};
 
var foo = function(){
 console.log(this);
};
 
foo(); // 全局变量 global
foo.apply(myObject); // { value: 100 }
foo.call(myObject); // { value: 100 }
 
var newFoo = foo.bind(myObject);
newFoo(); // { value: 100 }

apply() 方法接受两个参数第一个是函数运行的作用域,另外一个是一个参数数组(arguments)。

call() 方法第一个参数的意义与 apply() 方法相同,只是其他的参数需要一个个列举出来。

简单来说,call 的方式更接近我们平时调用函数,而 apply 需要我们传递 Array 形式的数组给它。它们是可以互相转换的。

现在来看一个题:

var a=10;
function test(){
a=5;
alert(a);
alert(this.a);
var a;
alert(this.a);
alert(a);
}
问:执行test()和new test() 返回值分别为啥?
答:返回结果,alert的内容:
test(): 5,10,10,5
new test():5,undefined,undefined,5

解释下:
在第一种情况 this指拥有test的对象,这儿是windows

第二种情况this指new创建的对象,因为未定义this.a,所以undefined

特别第二种情况,注意函数内部的a是没有var的,所以被定义成了一个全局变量


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值