【笔记】探索js 的this 对象 (第二部分)
了解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 对象 (第二部分)的更多相关文章
- 【笔记】探索js 的this 对象 (第一部分)
最近在看 你不知道的javascript 这本书,在第二部分看到了一个比较重要的知识点 那就是 this对象的全面认识,于是做一下笔记 博主本人在看这本书之前也一直以为 this 是指一切引用类型的本 ...
- 【笔记】探索js 的this 对象 (第三部分)
了解完函数的调用区域是如何影响this 对象的,还有this 的各种绑定方式以及各种绑定方式的优先级后 最后一部分,来了解一下this 的一些例外情况 1.被忽略的this 例如在使用bind 方法时 ...
- 超全面的JavaWeb笔记day03<JS对象&函数>
1.js的String对象(****) 2.js的Array对象 (****) 3.js的Date对象 (****) 获取当前的月 0-11,想要得到准确的月 +1 获取星期时候,星期日是 0 4.j ...
- 4月5日--课堂笔记--JS内置对象
JavaScript 4.5 一. JS内置对象 1.数组Array a)创建语法1:var arr=new Array(参数); i. 没有参数:创建一个初始容量为0的数组 ii. ...
- 读书笔记-你不知道的JS上-对象
好想要对象··· 函数的调用位置不同会造成this绑定对象不同.但是对象到底是什么,为什么要绑定他们呢?(可以可以,我也不太懂) 语法 对象声明有两个形式: 1.字面量 => var obj = ...
- Node.js学习笔记(四): 全局对象
在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性. 这 ...
- 5月15日上课笔记-js中 location对象的属性、document对象、js内置对象、Date事件对象、
location的属性: host: 返回当前主机名和端口号 定时函数: setTimeout( ) setInterval() 二.document对象 getElementById(); 根据ID ...
- web前端学习(四)JavaScript学习笔记部分(6)-- js内置对象
1.JS内置对象-什么是对象 1.1.什么是对象: JavaScript中的所有事物都是对象:字符串.数值.数组.函数 每个对象带有属性和方法 JavaScript允许自定义对象 1.2.自定义对象: ...
- 《JavaScript权威指南》学习笔记 第五天 window对象的方法。
前天和昨天大致浏览了犀牛书的函数.类与模块.正则表达式.JavaScript扩展.以及服务端的js.这些方面对于我目前的水平来说比较难,一些最基本的概念都不能领会.不过最复杂的知识占用平时使用的20% ...
随机推荐
- chattr命令的用法
chattr (配置文件隐藏属性)[root@www ~]# chattr [+-=][ASacdistu] 文件或目录名称选项与参数:+ :添加某一个特殊参数,其他原本存在参数则不动.- :移除某一 ...
- ARM开发板不工作的几个原因
刚焊了5块ARM(LPC2478)的开发板,上程序测试了一下,发现只有一个板子工作其他四个全部歇菜.努力地找了一会最终发现是板子的来个电阻焊翻了.因为是1206 的封装而且来个电阻在PCB上摆放的位置 ...
- Python开发基础-Day4-布尔运算、集合
布尔值 True 真 False 假 所有的数据类型都自带布尔值,数据只有在0,None和空的时候为False. print(bool()) print(bool()) print(bool('')) ...
- Xamarin Android SDK无法更新的解决办法
Xamarin Android SDK无法更新的解决办法 Xamarin Android SDK无法更新的解决办法,更新时候,提示警告信息:A folder failed to be moved. ...
- BZOJ 4403 序列统计(Lucas)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4403 [题目大意] 给定三个正整数N.L和R,统计长度在1到N之间, 元素大小都在L到 ...
- 【线段树+离散化】POJ2528-Mayor's posters
[题目大意] 在墙上贴海报,问最后能看到几张海报? [注意点] 1.首先要注意这是段线段树,而非点线段树.读题的时候注意观察图.来看discuss区下面这组数据: 3 5 6 4 5 6 8 上面数据 ...
- 【线段树】HDU1394 - Minimum Inversion Number
[题目大意] 给出0..n-1组成的一段数,可以移动前几个数到结尾.求出最小的逆序对个数. [思路] 先用线段树求出逆序对,方法和树状数组是一样的.然后对于当前第一个数num[0],在它之后比它小的数 ...
- POJ 2139 Six Degrees of Cowvin Bacon (弗洛伊德最短路)
题意:奶牛拍电影,如果2个奶牛在同一场电影里演出,她们的合作度是1,如果ab合作,bc合作,ac的合作度为2,问哪一头牛到其他牛的合作度平均值最小再乘100 思路:floyd模板题 #include& ...
- JS操作小数运算,结果莫名其妙出现多位小数问题
Number类型: Number类型是ECMAScript中最常用和最令人关注的类型了:这种类型使用IEEE754格式来表示整数和浮点数值(浮点数值在某些语言中也被成为双精度数值),为支持各种数据类型 ...
- BabyLinux制作过程详解
转:http://www.360doc.com/content/05/0915/14/1429_12641.shtml BabyLinux制作过程详解 作者:GuCuiwen email:win2li ...