关键词:
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笔记
类型:JavaScript有7种内置类型空值(null)未定义(undefined)布尔值(boolean)数字(number)字符串(string)对象(object)符号(symbol) 除对象以外,其他统称为“基本类型” 用typeof运算符来查看值的类型typeofundefined ==="undefi... 查看详情
你不知道的javascript笔记
...算符则相当于标点符号和连接词。 JavaScript中表达式可以返回一个结果值。 vara=3*6; varb=a; b; &nbs 查看详情
你不知道的javascript中,读书笔记
七种内置类型null,undefined,boolean,number,string,object,symboltypeofnull===‘object‘//truenull是typeof是object的唯一的假值typeoffunction会返回‘function‘使用typeofx!==‘undefined‘比直接判断x更加安全,因为不会引发referenceerror 查看详情
你不知道的javascript笔记
this和对象原型this是一个很特别的关键字,被自动定义在所有函数的作用域中//foo.count是0,字面理解是错误的 functionfoo(num){ console.log("foo:"+num); &n 查看详情
你不知道的javascript(上卷)读书笔记之一----作用域
你不知道的Javascript(上卷)这本书在我看来是一本还不错的书籍,这本书用比较简洁的语言来描述Js的那些”坑”,在这里写一些博客记录一下笔记以便消化吸收。1编译原理在此书中,开始便提出:Javascript是一门编译型语言,我... 查看详情
你不知道的javascript笔记
规避冲突functionfoo(){functionbar(a){i=3;console.log(a+i);}for(vari=0;i<10;i++){bar(i*2)}} //11无限死循环 区分函数声明和函数表达式最简单的方法是看function关键字出现的位置,如果function是声明中的第一个词,那么是函数声明,否则是... 查看详情
你不知道的javascript--上卷--读书笔记1
作用域是什么? 答:在《你不知道的javascript》书中提到,作用域就是根据名称查找变量的一套规则。古语有“无规矩不成方圆”,但是没有方圆,规矩又给谁用?所以个人理解作用域就是“规矩”+”方圆“。作用域是在创... 查看详情
你不知道的javascript-上卷の读书笔记
...; 1— 作用域对JavaScript而言,大部分情况下编译发生 查看详情
你不知道的javascript--上卷--读书笔记2
...以访问它们被定义时所处的作用域中的任何变量,这就是JavaScript的闭包。闭包有哪些应用? 答:函数作为返回值:functionfoo(){vara=2;functionbar(){//bar拥有涵盖foo作用域的闭包,并对它保持 查看详情
javascript中的this—你不知道的javascript上卷读书笔记
this是什么?this是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。当一个函数被调用时,会创建一个活动记录(有时... 查看详情
你不知道的javascript学习笔记1——作用域
处理程序三要素:引擎:编译与执行过程。编译器:语法分析与代码生成等。作用域:收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。&nb... 查看详情
你不知道的javascript(上卷)读书笔记之二----词法作用域
...要的工作类型,一种是词法作用域,一种是动态作用域,Javascript采用的是词法作用域,关于动态作用域的有兴趣的可以自行Google。1.词法阶段 首 查看详情
《你不知道的javascript上卷》学习笔记(代码片段)
第一部分:作用域和闭包一、作用域1.作用域:存储并查找变量的规则2.源代码在执行之前(编译)会经历三个步骤:分词/此法分析:将代码字符串分解成有意义的代码块(词法单元)解析/语法分析:将词法单元流转换成抽象语... 查看详情
你不知道的javascript上卷-读书笔记-第2章词法作用域-2.2欺骗词法(代码片段)
你不知道的JavaScript上卷-读书笔记-第2章词法作用域-2.2欺骗词法作用域`eval`和`with`的缺点作用域JavaScript在ES6以前只有函数作用域。ES6开始支持块作用域:通常就是包裹的范围作用域中查找变量or函数的规则是从当前向... 查看详情
你不知道的javascript上卷-读书笔记-第2章词法作用域-2.2欺骗词法(代码片段)
你不知道的JavaScript上卷-读书笔记-第2章词法作用域-2.2欺骗词法作用域`eval`和`with`的缺点作用域JavaScript在ES6以前只有函数作用域。ES6开始支持块作用域:通常就是包裹的范围作用域中查找变量or函数的规则是从当前向... 查看详情
读书笔记你不知道的javascript(上卷)--作用域是什么
...1、理解作用域几个名词的介绍引擎:从头到尾负责整个JavaScript程序的编译及执行过程编译器:负责语法分析及代码生成器等脏活累活作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严... 查看详情
读书笔记《你不知道的javascript(上卷)》——第二部分this和对象原型(代码片段)
文章目录第6章行为委托6.1面向委托的设计6.1.1类理论6.1.2委托理论1.互相委托(禁止)2.调试6.1.3比较思维模型6.2类与对象6.2.1控件“类”ES6的class语法糖6.2.2委托控件对象6.3更简洁的设计反类6.4更好的语法反词法6... 查看详情
js你不知道的javascript笔记-this-四种绑定规则-绑定优先级-绑定例外-箭头函数(代码片段)
文章目录1.为什么要用`this`2.关于`this`的误解2.1`this`不是指向函数自身2.2`this`不指向函数的词法作用域3.什么是调用栈与调用位置4.`this`的绑定规则4.1默认绑定`fun()`4.2隐式绑定`obj.fun()`隐... 查看详情