你不知道的javaScript笔记(2)
this和对象原型
this是一个很特别的关键字,被自动定义在所有函数的作用域中
// foo.count 是0,字面理解是错误的
function foo(num) {
console.log("foo:"+ num);
this.count++;
}
foo.count = 0;
var i;
for(i=0;i<10;i++){
if(i>5){
foo(i)
}
}
console.log(foo.count) //0
// 使用词法作用域解决问题
function foo(num) {
console.log("foo:"+ num);
data.count++;
}
var data = {
count:0
};
var i;
for(i=0;i<10;i++){
if(i>5){
foo(i)
}
}
console.log(data.count); // 4
// 用foo标识符来替代this来引用函数对象,回避了this 的问题,完全依赖于变量foo的词法作用域。
function foo(num) {
console.log("foo:"+ num);
foo.count++;
}
foo.count = 0
var i;
for(i=0;i<10;i++){
if(i>5){
foo(i)
}
}
console.log(foo.count) //4
//强制this 指向foo函数对象
function foo(num) {
console.log("foo:"+num);
this.count++
}
foo.count = 0;
var i;
for(i=0; i< 10; i++){
if(i>5){
foo.call(foo,i);
}
}
console.log(foo.count) //4
this是在运行是 绑定的,并不是在编写时绑定的,它的上下文取决于函数调用时的各种条件,this的绑定和和函数声明的位置没有任何关系,只取决于函数调用的方式。
this全面解析
调用栈与调用位置
function baz(){
//当前调用栈是:baz
// 因此,当前的调用中位置是全局作用域
console.log("baz");
bar(); // <--bar的调用位置
}
function bar(){
//当前的调用栈是: baz-> bar
// 因此,当前调用位置在baz
console.log("bar);
foo(); // <-- foo 的调用位置
}
function foo(){
//当前的调用栈是: baz-> bar->foo
// 因此,当前调用位置在bar
console.log("foo");
}
baz(); // <-- baz 的调用位置
只有运行在非strict mode 下,默认绑定才能绑定到全局对象。
对象属性引用链中只有最顶层或者说最后一层灰影响调用位置。
function foo() {
console.log(this.a);
}
var obj2 = {
a: 42,
foo:foo
};
var obj1 = {
a:2,
obj2: obj2
};
obj1.obj2.foo(); // 42
硬绑定的典型应用场景就是创建一个包裹函数,传入所有的函数并返回接收到的所有的值。
function foo(something){
console.log(this.a,something);
return this.a + something;
};
var obj = {
a:2
};
var bar = function() {
return foo.apply(obj,arguments);
};
var b = bar(3) ; // 2 3
console.log(b) // 5
另一种方法是创建一个i可以重复使用的辅助函数
function foo(something){
console.log(this.a, something);
return this.a + something;
}
// 简单的辅助绑定函数
function bind(fn,obj){
return function(){
return fn.apply(obj,arguments);
};
}
var obj = {
a:2
}
var bar = bind(foo,obj);
var b = bar(3); // 2 3
console.log(b) // 5
ES5 中提供了内置的方法 Function.prototype.bind, bind(..) 会返回一个硬编码的新函数,它会
把参数设置为this的上下文并调用原始函数。
function foo(something){
console.log(this.a, something);
return this.a + something;
}
var obj = {
a:2
}
var bar = foo.bind(obj);
var b = bar(3); // 3 5
console.log(b) // 5
API 调用的 上下文
function foo(el){
console.log(el,this.id);
}
var obj = {
id: "awesome'
}
// 调用 foo(..)时把this 绑定到obj
[1,2,3].forEach(foo,obj);
// 1 awesome 2 awesome 3 awesome
new可以影响函数调用时this 绑定行为的方法。
function foo(a){
this.a = a;
}
var bar = new foo(2);
console.log(bar.a); // 2
判断this
1.函数是否在new 中调用(new 绑定)? 如果是的话this 绑定的是新创建的对象。
var bar = new foo();
2.函数是否通过call , apply (显示绑定) 或者硬绑定调用? 如果是的话,this的绑定时指定的对象。
va bar = foo.call(obj2)
3.函数是否在某个上下文对象中调用(隐式绑定) ? 如果是的话,this 的绑定时在那个上下文。
var bar = obj1.foo()
4.如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到全局对象上。
var bar = foo();
软绑定
function foo(){
console.log("name:" + this.name);
}
var obj = {name: "obj"},
obj2 = {name: "obj2"},
obj3 = {name: "obj3"},
obj3 = {name: "obj3"};
var foo0BJ = foo.softBind(obj);
foo0BJ(); // name:obj
obj2.foo = foo.softBind(obj);
obj2.foo(); // name:obj3 <--看!
setTimeout(obj2.foo,10);
// name:obj <--- 应用了软绑定
你不知道的javaScript笔记(2)的更多相关文章
- 你不知道的JavaScript笔记----对象
对象: 1.定义对象属性 属性描述符(也称为:数据描述符) Object.defineProperty(Object,PropertyName,{ value: 6, writable: true, ...
- 你不知道的javaScript笔记(7)
异步:现在与将来 分块的程序 可以把JavaScript 程序写在单独的js 文件中,这个程序是由多个块组成的,这些块 中只有一个是现在执行,其余在捡来执行,最常见的块单位是函数. 例如: funct ...
- 你不知道的javaScript笔记(6)
语法 语句表达式 句子是完整表达某个意思的一组词,由一个或多个短语组成,他们之间由标点符号或者连接词连接起来. 语句相当于句子,表达式相当于短语,运算符则相当于标点符号和连接词. JavaScript ...
- 你不知道的javaScript笔记(5)
原生函数 常用的原生函数 String() Number() Boolean() Array() Object() Function() RegExp() Date() Error() Symbol( ...
- 你不知道的javaScript笔记(4)
类型: JavaScript 有7种内置类型 空值 (null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(string) 对象(object) 符号(sy ...
- 你不知道的javaScript笔记(3)
对象 对象可以通过两种形式定义: 声明形式和构造形式 声明形式语法: var myObj = {key:value} 构造形式语法: var myObj = new Object(); myObj.k ...
- 你不知道的javaScript笔记(1)
规避冲突 function foo(){ function bar(a){ i = 3; console.log(a + i); } for ( var i=0; i < 10; i++){ b ...
- 你不知道的Javascript(上卷)读书笔记之一 ---- 作用域
你不知道的Javascript(上卷)这本书在我看来是一本还不错的书籍,这本书用比较简洁的语言来描述Js的那些"坑",在这里写一些博客记录一下笔记以便消化吸收. 1 编译原理 在此 ...
- 你不知道的JavaScript上卷笔记
你不知道的JavaScript上卷笔记 前言 You don't know JavaScript是github上一个系列文章 初看到这一标题的时候,感觉怎么老外也搞标题党,用这种冲突性比较强的题目 ...
随机推荐
- 使用c#正则验证关键字并找出匹配项
在.net里,使用类Regex可以正则验证一些关键字并取出匹配项. 1.使用Regex.IsMatch(string input, string pattern, RegexOptions ...
- java实例初始化块
实例初始化程序块用于初始化实例数据成员. 它在每次创建类的对象时运行.实例变量的初始化可以是直接的,但是可以在初始化实例初始化块中的实例变量时执行额外的操作. 什么是实例初始化块的使用,我们可以直接分 ...
- ZROJ#397. 【18提高7】模仿游戏(爆搜)
题意 题目链接 Sol 考试的时候调了1.5h没调出来我真是菜爆了... 读完题目后不难发现,每次约束的条件相当于是\(b[((x[i] + i) % N + (i / N) % N) % N] = ...
- HTML标签 链接 随笔3
4-1 <a>标签 网页链接 使用<a>标签可实现超链接,它在网页制作中可以说是无处不在,只要有链接的地方,就会有这个标签. 语法: <a href="目标网 ...
- setTimeout的实现原理以及setTimeout(0)的使用场景
先看一段代码: var start = new Date(); setTimeout(function(){ var end = new Date(); console.log("Tim ...
- android 5.0 下载编译
CM的CM-12.0版本(对应Android5.0.2): $ repo init -u https://github.com/CyanogenMod/android.git -b cm-12.0 注 ...
- IT集中监控
监控的从底层到上应该是: 一 数据采集层 二 数据处理层 三 数据展示层 监控需要和ITIL中定义的服务进行相当多的交互,例如监控会使用配置管理数据库CMDB来记录和读取数据,会将事件处理方式从知识库 ...
- solidity语言7
单位和全局变量 Ether Units: wei, finney, szabo, ether Time Units: 1 == 1 seconds 1 minutes == 60 seconds 1 ...
- log4go的一些改进设想
log4go 的 4.0.2 版本(https://github.com/ccpaging/log4go/tree/4.0.2)发布以后, 看了看别的 go 语言日志文件设计.发现了一篇好文: log ...
- 1.GlusterFS 初识
一. GlusterFS 初始 1.1 分布式文件系统出现 计算机通过文件系统管理.存储数据,而现在数据信息爆炸的时代中人们可以获取的数据成指数倍的增长,单纯通过增加硬盘个数来扩展计算机文件系统的存储 ...