---恢复内容开始---

一、this是什么东东?

  this是指包含它的函数作为方法被调用时所属的对象。这句话理解起来跟卵一样看不懂,但是如果你把它拆分开来变成这三句话后就好理解一点了。

  1.包含它的函数

  2.作为方法被调用时

  3.所属的对象

二、this的绑定规则

  1、默认绑定  

var x = ;
function num(){
this.x = ;
}
console.log(this.x);//
num();
console.log(this.x);//1 //当没有使用let或者var时,声明的变量是全局变量,指向window,
//在这一形态下,其函数内部的this是与全局作用域时一样,直接指向window,执行完num()后,更改了x的值,所以其形态 依然等价于window。
      function foo(){
      console.log(this.a)     }     var a = ;     foo(); //     console.log(this.document === document); // true     // 在浏览器中,全局对象为 window 对象:     console.log(this === window); // true     this.a = ;     console.log(window.a); //     this指向全局对象。在非严格模式中,当funcion被不带任何修饰的函数直接引用进行调用的,只能使用默认绑定,无法应用其他规则  

    

  2、隐式绑定

    先看两段例子   

function foo(){
console.log(this.a)
} var obj = {
a:,
foo:foo
} obj.foo() //2
//隐式绑定————调用位置使用obj上下文来引用函数,可以说函数被调用时obj对象“拥有”或者“包含”它,它就指向谁。
 
function foo(){
console.log(this.a)
} var obj2 = {
a:,
foo:foo
} var obj1 = {
   a:,
   obj2:obj2,
   foo:foo
}
obj1.foo() //2
obj1.obj2.foo() //42
//此时可以控制台查看obj1,obj2对象里究竟包含了什么
//当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象
//对象属性引用链中只有最后一层在调用位置中起作用

下面思考这一段会输出什么呢?

function foo(){
console.log(this.a)
} var obj = {
a:,
foo:foo
} var bar = obj.foo; //这里bar将引用foo函数本身,所以不带有函数对象的上下文,this会直接指向window
bar() //?

//为什么没有隐式绑定?这种情况称为隐式丢失。
//因为bar=obj.foo 而obj.foo指向foo 也就是bar = function foo(){console.log(this.a)} foo中的this指向window,
//在window中并没有对a进行定义,so,结果是undefined

接下来再看一段会是什么结果呢?(参数传递时的隐式赋值)

function foo(){
console.log(this.a)
} function doback(fn){
fn()
} var obj = {
a:,
foo:foo
} var a = 'global'; doback(obj.foo) //? 显然答案是global,但是为什么呢?请继续往下看! //隐式丢失--被隐式绑定的函数会丢失绑定对象然后应用默认绑定。
//最后函数执行 doback(obj.foo)时,会进行参数传递,也就是 fn = obj.foo,就和上一个例子一样了。既this指向的是window。

  

  3、显示绑定

function foo(){
console.log(this.a)
} var obj = {
a:
}
foo.call(obj) //2 //显式绑定--第一个参数是一个对象,接着在调用函数时将其绑定到this,通过foo.call(obj),我们可以在调用foo时强制把他的this绑定到obj上
function foo(){
console.log(this.a)
} var obj = {
a:
} var a = '3333333'; var bar = function(){
foo.call(obj)
}
bar() // 2
bar.call(window) //2

// 硬绑定后bar无论怎么调用,都不会影响foo函数的this绑定
// 通过创建函数bar(),并在内部调用foo.call(obj),强制把foo的this绑定到obj上。硬绑定的bar之后无论如何调用函数,都只会在obj上调用foo。
我们来看一下他的应用:
function foo(num) {
console.log( this.a, num);
return this.a + num;
} var obj = {
a:
}; var bar = function() {
return foo.call( obj, ...arguments ); // 将obj对象硬编码进去
   //return foo.apply( obj, arguments ); // 也可以使用apply将obj对象硬编码进去
};

var b = bar(  ); // 2 3
console.log( b ); //

function fn1(){
console.log();
}
function fn2(){
console.log();
} fn1.call(fn2); //输出 1 fn1.call.call(fn2); //输出 2 这个暂时没有搞懂,但是东鸽子大师中有讲解,感兴趣的小伙伴可以看看。

  

  4、new绑定

    我们不去深入了解构造函数,但要知道new来调用函数,或者说发生构造函数调用时,执行了哪些

    当代码 new foo(...) 执行时:

    (1) 创建一个新对象,它继承自foo.prototype.

    (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);new foo 等同于 new foo(),只能用在不传递任何参数的情况。

    (3) 执行构造函数中的代码(为这个新对象添加属性) ;

    (4) 返回新对象, 那么这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那么new出来的结果为步骤1创建的对象。

function foo(a){
this.a = a;
} var bar = new foo(); //创建一个新对象bar,它继承了foo.prototype. 也就是bar这个对象有a这个属性,且传进去的是2,使用new来调用foo(..)时,会构造一个新对象,并把它绑定到foo(..)调用中的this上
console.log(bar.a) //2 

三、下面做一个小练习看看你学会了吗?

例一:

function foo(a){
console.log(this.a)
} var obj1 = {
a:,
foo:foo
} var obj2 = {
a:,
foo:foo
} obj1.foo() //?
obj2.foo() //? obj1.foo.call(obj2) //?
obj2.foo.call(obj1) //? 答案:
obj1.foo() //2 隐式绑定
obj2.foo() //3 隐式绑定 obj1.foo.call(obj2) //3 显式绑定
obj2.foo.call(obj1) //2 显式绑定
通过答案得出:显示绑定 > 隐式绑定
显示绑定优先级更高,所以在判断时 应当 优先考虑 是否 存在 显示绑定
例二:

function foo(someting){
this.a = someting
} var obj1 = {
foo:foo
}
var obj2 = {}
obj1.foo()
var bar = new obj1.foo()
console.log(obj1.a)//?
console.log(bar.a)//? 答案:
console.log(obj1.a) //2
console.log(bar.a) //4 通过答案得出: new绑定 > 隐式绑定
显示绑定优先级更高,所以在判断时 应当 优先考虑 是否 存在 new绑定
需要注意的是:new和call/apply无法一起使用,因此无法通过new foo.call(obj)来直接测试

function foo(someting){
this.a = someting
} var obj1 = {} var bar = foo.bind(obj1) //不知道bind()方法的同学可以直接点击此处查看最骚的就是你同学贡献的详解。
bar()
console.log(obj1.a)//? var baz = new bar()
console.log(obj1.a)//?
console.log(baz.a)//? 答案:2 2 3 通过答案得出:new绑定 > 显示绑定
new修改了硬绑定调用bar(..)中的this,因为使用了new绑定,得到了一个名字为baz的新对象,并且baz.a的值为3.
所以 new绑定 > 显示绑定 > 隐式绑定 > 默认绑定

在此特别鸣谢同事Jason大哥的share!!!

---恢复内容结束---

关于JavaScript中this的指向,你知晓几分?请速来围观!的更多相关文章

  1. 关于Number的属性和方法你知晓几分?速来围观!

    1.Number.isFinite() 方法用来检测传入的参数是否是一个有穷数(finite number)返回值为布尔值. 和全局的 isFinite() 函数相比,这个方法不会强制将一个非数值的参 ...

  2. javascript中this的指向

    作为一个前端小白在开发中对于this的指向问题有时候总是会模糊,于是花时间研究了一番. 首先this是JS的关键字,this是js函数在运行是生成的一个内部对象,生成的这个this只能在函数内部使用. ...

  3. Javascript中的this指向。

    一.JavaScript中的函数 在了解this指向之前,要先弄明白函数执行时它的执行环境是如何创建的,这样可以更清楚的去理解JavaScript中的this指向. function fn(x,y,n ...

  4. JavaScript中 this 的指向

    很多人都会被JavaScript中this的指向(也就是函数在调用时的调用上下文)弄晕,这里做一下总结: 首先,顶层的this指向全局对象. 函数中的this按照调用方法的不同,其指向也不同: 1.函 ...

  5. 前端面试之JavaScript中this的指向【待完善!】

    JavaScript中this的指向问题! 另一个特殊的对象是 this,它在标准函数和箭头函数中有不同的行为. 在标准函数中, this 引用的是把函数当成方法调用的上下文对象,这时候通常称其为 t ...

  6. JavaScript中的this指向

    this是谁 技术一般水平有限,有什么错的地方,望大家指正. this代指当前对象super调用父类的构造函数,应表会运网数物,加载驱动建立链接执行SQL处理结果,直到现在每想起这三点就能想起我上大学 ...

  7. Javascript 中的this 指向的对象,你搞清楚了吗?

    Javascript 中的this 总让人感到困惑,你能分清以下三种test1(),test2(),test3() 情况下的输出吗? 注:以下Javascript运行环境中为浏览器 //1 this在 ...

  8. javascript中的this指向问题

    在深入学习JavaScript之后,我们越来越多的会遇到函数或者在对象内部中,对于this的指向问题的疑惑,其实基本上每一个编程语言中都有一个this,这个this的指向都是大同小异,你也可以汉化它的 ...

  9. 谈谈 JavaScript 中的 this 指向问题

    JavaScript 中的 this 为一个重难点,它不像静态语言 C#.Java 一样,就表示当前对象.而在 JS 中, this 是运行时确定,而并非定义时就已确定其值. 谈起 this ,必须少 ...

随机推荐

  1. 备份和恢复ZBrush文件

    ZBrush可以自动保存绘图的备份副本,并在发生系统错误时提醒您恢复备份副本.当ZBrush软件遇到崩溃.导致错误.非正常退出的时候,可能之前所做的努力就会功亏一篑,那么,在ZBrush软件中能否将文 ...

  2. css——外部样式

    外部样式 先建立一个css文件,如下: 然后开始写代码,不要加<style> 然后可以在html文件中的<head>内引用:<link rel="stylesh ...

  3. 一些css兼容问题

    由于各浏览器的不同,会存在一些兼容问题,特别是兼容IE6/7/8 下面简单介绍了一些解决方法,更多问题可以访问 W3help.org来查看. 可以通过js获取浏览器版本 document.body.i ...

  4. BZOJ 1014 [JSOI2008]火星人prefix (splay+二分答案+字符串hash)

    题目大意:维护一个字符串,支持插入字符和替换字符的操作,以及查询该字符串两个后缀的最长公共前缀长度 乍一看以为是后缀数组,然而并没有可持久化后缀数组(雾) 看题解才知道这是一道splay题,首先要对s ...

  5. 详解 QT 主要类 QWidget

    QWidget类是所有用户界面对象的基类,每一个窗口部件都是矩形,并且它们按Z轴顺序排列的.一个窗口部件可以被它的父窗口部件或者它前面的窗口部件盖住一部分. 先来看内容. AD: 2013云计算架构师 ...

  6. WebService 布置简单的计算器

    实验环境:myeclipse2015 具体的过程如下: 首先建立一个web service project 命名就为WebServiceProject,同时选择web service framewor ...

  7. vue路由传值params和query的区别

    vue路由传值params和query的区别1.query传参和接收参数传参: this.$router.push({ path:'/xxx' query:{ id:id } })接收参数: this ...

  8. 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] B】Battleship

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 暴力枚举船的左上角. 然后统计每个点被覆盖次数就好. [代码] #include <bits/stdc++.h> #de ...

  9. 在Action中获取servlet API

    Struts2的Action组件是不依赖servlet API 的.那么当你在action中的业务需要处理HttpServletRequest和HttpServletResponse的时候(比如要对响 ...

  10. linux内核(二)内核移植(DM365-DM368开发攻略——linux-2.6.32的移植)

    一.介绍linux-2.6.32: Linux-2.6.32的网上介绍:增添了虚拟化内存 de-duplicacion.重写了 writeback 代码.改进了 Btrfs 文件系统.添加了 ATI ...