了解this 对象之后 我们明白了this 对象就是指向调用函数的作用域
那么接下来我们便要清除函数究竟在哪个作用域调用
找到调用的作用域首先要了解一下几点:

1、调用栈: 调用栈就是一系列的函数,表明当前函数是由哪些上层函数调用的包括它自身,我们关心的调用位置就在当前正在执行的函数的前一个调用中。

function baz(){
//调用栈:baz 函数的内部 console.log("baz 函数内部");
bar();
} function bar(){
//调用栈分别是baz -> bar
//调用位置为 baz 因此bar 的this指针指向 baz console.log("bar 函数内部");
foo();
} function foo(){
//调用栈分别为 baz -> bar -> foo
//调用位置是bar 内部 因此 foo的 this 指针指向了 bar console.log("foo 函数的内部");
} baz()//baz的调用位置是 全局作用域

这段代码的意思是,函数再哪个区域被调用 那个区域就是它的执行环境

找到了调用位置就要理解一下函数对 this对象的绑定了
一般分为一下4种:

1、默认绑定

指函数在调用的过程中没有任何干涉调用位置的代码 浏览器引擎根据调用栈默认绑定

默认绑定,函数的this 对象会指向了window 对象 而在严格模式下函数访问this 会显示undefined

例子:

function foo(){
console.log(this.a);
}
var a = "i'm window";
foo();//输出2 因为全局变量也是window对象的属性

2、隐式绑定

函数没有调用任何方法绑定 而是在调用时根据对象上下文绑定了this 的作用域

看一下下面的例子

function foo(){
console.log(this.a);
} var obj = {
a: "i'm obj",
foo: foo //对象obj 中包含着 foo的引用
} obj.foo();

//通过obj 调用 函数foo,所以foo的this 对象绑定在了 obj上
//严格来说 函数foo 不属于obj对象 但由于函数是通过obj 引用并调用的所以this 指向了obj

 

另外对象调用链中只有最靠近被调用函数那层会影响函数的调用位置

即:函数在某一个对象里面 通过那个对象调用函数 this永远指向那个对象

例如:

function bar(){
console.log(this.a);
} var obj2 = {
a: "i'm obj2",
bar: bar,
} var obj1 = {
a: "i'm obj1",
obj2: obj2,
bar: bar
} obj1.obj2.bar();

这里的意思是:obj1 调用 obj2 然后obj2 再调用 bar这个函数引用

从逻辑上说 bar这个函数调用怎么也是属于 obj2 吧

另外dom 的事件绑定回调函数也会把this 绑定在执行事件的 dom元素对象上

小分支:

2.1、隐式丢失

隐式绑定的函数会丢失原来的this所引用的对象
丢失后的this 会引用到全局对象或 undefined

例1:
把函数的引用赋值给全局变量 会丢失原来的this 绑定

function foo(){
console.log(this.a);
} var obj = {
a: "i'm obj",
foo: foo
} var bar = obj.foo; //把obj foo属性里面对 foo 函数的引用赋值给了全局变量bar var a = "global window";
bar();

这里的函数 foo 的引用虽然是obj 里面的一个属性值,但是后面却把函数的引用赋值给了一个全局变量并且在全局环境执行,所以foo 的this 对象指向了window 对象

其实这里真正的误区是我们一直以为在对象字面量中属性值为函数就是函数this 绑定的区域,其实不然

回顾一下第一部分的话,函数在哪里调用,那里才是它this 对象绑定的环境

所以这次函数 foo的引用在(保存在了bar中)在全局调用所以this 指向了全局

例2:

把函数的引用当作参数传进另外一个函数被执行 会造成隐式丢失

function foo(){
console.log(this.a);
} function dofoo(fn){
fn();
} var obj = {
a: "i'm obj",
foo: foo
} var a = "global window"; dofoo(obj.foo);

这里 dofoo 的输出结果是  "global window"

同时,回调函数也会造成隐式丢失

setTimeout(obj.foo,1000);//"global window"

3、显式绑定

通过语言内置的方法 将函数硬性绑定在了某一对象上执行
例如通过 call(),apply(),bind() 方法
此时函数的this 对象绑定在了bind() 和 apply() 方法的参数上

例如:

function foo(){
console.log(this.a);
} var obj = {
a: "i'm obj",
} // 把foo函数绑定在obj 上执行 foo.call(obj);//i'm obj

3.1、硬绑定

通过提供的方法,将函数绑定在某一对象上执行
例:

function foo(){
console.log(this.a);
} var obj = {
a: "i'm obj",
} setTimeout(function timer(){
//回调函数通常会丢失this
//在回调函数中使用硬性绑定就不会出现这个现状了 foo.call(obj);//把foo 硬性绑定在obj 上执行 },1000);//i'm obj obj.call(window);//硬性绑定之后 无法再绑定其他对象

apply和call 方法能够执行这种硬性绑定

除了这两个 es5 语法还定义了新方法 bind()

例:

function foo(num){
return this.a + num;
} var obj = {
a: 2
} var bar = foo.bind(obj);//把foo 函数的引用绑定在了 obj上 var result = bar(3); console.log(result);//

new 绑定:

js 的new 关键字不等同于其他面向对象语言里的new
js 的new 关键字仅仅是调用它的目标函数而已
1、调用new 关键字会创建一个新对象
2、新对象会与函数的原型连接
3、将函数的this 绑定到了新对象上
4、如果函数没有返回指定的新对象 那么就会返回一个默认的对象

例:

function foo(){
this.a = "who can take me go";
} var bar = new foo();
console.log(bar.a);

上例中我们通过new 将foo函数实例化 并将this 指针指向了bar
于是bar 便拥有了函数中的 a属性

以上四种绑定的优先级

默认绑定最低
隐式绑定低于显示绑定
隐式绑定又低于 new绑定
而new 与显示绑定其实两个本身的并没有什么影响很难说明优先级

如下例:

function foo(arg1){
this.a = arg1;
} var obj = {}; var bar = foo.bind(obj);
// 将foo 函数的引用绑定在obj 上
// 然后将obj 上对函数foo 的引用传值给 bar bar(2);
console.log(obj.a); //现在将引用这 foo.bind(obj)的变量bar 实例化
var baz = new bar(5);
console.log(baz.a);//
//此操作没有修改obj 的属性a 值,并且把新值添加到了新的对象上 baz

小结:

这部分内容主要讲述了函数的this绑定位置以及各种的绑定方式,有如下结论

1、当函数被new 实例化时,this 对象指向新返回的对象

2、当函数调用了 call(),apply()或者 bind(),this绑定在指定的对象

3、函数在某个对象字面量里面调用,this绑定在了这个对象字面量里面

4、以上都没有被操作,在非严格模式下函数的this 指向了window对象,严格模式下为undefined

【笔记】探索js 的this 对象 (第二部分)的更多相关文章

  1. 【笔记】探索js 的this 对象 (第一部分)

    最近在看 你不知道的javascript 这本书,在第二部分看到了一个比较重要的知识点 那就是 this对象的全面认识,于是做一下笔记 博主本人在看这本书之前也一直以为 this 是指一切引用类型的本 ...

  2. 【笔记】探索js 的this 对象 (第三部分)

    了解完函数的调用区域是如何影响this 对象的,还有this 的各种绑定方式以及各种绑定方式的优先级后 最后一部分,来了解一下this 的一些例外情况 1.被忽略的this 例如在使用bind 方法时 ...

  3. 超全面的JavaWeb笔记day03<JS对象&函数>

    1.js的String对象(****) 2.js的Array对象 (****) 3.js的Date对象 (****) 获取当前的月 0-11,想要得到准确的月 +1 获取星期时候,星期日是 0 4.j ...

  4. 4月5日--课堂笔记--JS内置对象

    JavaScript 4.5 一.    JS内置对象 1.数组Array a)创建语法1:var arr=new Array(参数); i.       没有参数:创建一个初始容量为0的数组 ii. ...

  5. 读书笔记-你不知道的JS上-对象

    好想要对象··· 函数的调用位置不同会造成this绑定对象不同.但是对象到底是什么,为什么要绑定他们呢?(可以可以,我也不太懂) 语法 对象声明有两个形式: 1.字面量 => var obj = ...

  6. Node.js学习笔记(四): 全局对象

    在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性. 这 ...

  7. 5月15日上课笔记-js中 location对象的属性、document对象、js内置对象、Date事件对象、

    location的属性: host: 返回当前主机名和端口号 定时函数: setTimeout( ) setInterval() 二.document对象 getElementById(); 根据ID ...

  8. web前端学习(四)JavaScript学习笔记部分(6)-- js内置对象

    1.JS内置对象-什么是对象 1.1.什么是对象: JavaScript中的所有事物都是对象:字符串.数值.数组.函数 每个对象带有属性和方法 JavaScript允许自定义对象 1.2.自定义对象: ...

  9. 《JavaScript权威指南》学习笔记 第五天 window对象的方法。

    前天和昨天大致浏览了犀牛书的函数.类与模块.正则表达式.JavaScript扩展.以及服务端的js.这些方面对于我目前的水平来说比较难,一些最基本的概念都不能领会.不过最复杂的知识占用平时使用的20% ...

随机推荐

  1. WordPress固定链接设置的几种方法(推荐/%post_id%.html)

    传说中,固定链接有SEO功能,今天试了试,现在给大家分享一下: wordpress固定链接设置技巧: 1.不要让日期出现在固定链接里面 这基于两个方面的考虑.一是如果数字出现在固定链接里面,等于提醒搜 ...

  2. Accord.NET入门

    0.序 园子里介绍Accord.NET的文章不少,但是具体讲如何使用的反而不多,可能跟.NET在机器学习领域应用不多有关.诚然,如果做项目的话,可能用Python更好一些,但是如果把了解Accord. ...

  3. 转:使用IDA动态调试WanaCrypt0r中的tasksche.exe

    逆向分析——使用IDA动态调试WanaCrypt0r中的tasksche.exe 转:http://www.4hou.com/technology/4832.html 2017年5月19日发布 导语: ...

  4. 2017CCPC 杭州 J. Master of GCD【差分标记/线段树/GCD】

    给你一个n个初始元素都为1的序列和m个询问q. 询问格式为:l r x(x为2or3) 最后求1~n所有数的GCD GCD:把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是 ...

  5. Loj#6433「PKUSC2018」最大前缀和(状态压缩DP)

    题面 Loj 题解 先转化题意,其实这题在乘了\(n!\)以后就变成了全排列中的最大前缀和的和(有点拗口).\(n\leq20\),考虑状压\(DP\) 考虑一个最大前缀和\(\sum\limits_ ...

  6. CentOS中Ctrl+Z、Ctrl+C、Ctrl+D的区别

    Ctrl+C和Ctrl+Z都是中断命令,但作用不同. Ctrl+C是发送SIGINT信号,终止一个进程. Ctrl+Z是发送SIGSTOP信号,挂起一个进程,将作业放置到后台(暂停状态).与此同时,可 ...

  7. 2017icpc 乌鲁木齐网络赛

    A .Banana Bananas are the favoured food of monkeys. In the forest, there is a Banana Company that pr ...

  8. hdu 1384 Intervals (差分约束)

    Intervals Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  9. [Codeforces-div.1 494B]Obsessive String

    [CF-div.1 B]Obsessive String 题目大意 两个字符串\(S,T\),求划分方案数使得一个集合中两两划分不相交且划分都包含字符串\(T\) 试题分析 kmp先求出那个位置匹配. ...

  10. 【CCpp程序设计2017】推箱子游戏

    我的还……支持撤销!用链表实现! 题目:推箱子小游戏(基于console) 功能要求: 将p09迷宫游戏改造为“推箱子”游戏: 在地图中增加箱子.箱子目标位置等图形: 当玩家将所有箱子归位,则显示玩家 ...