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)的更多相关文章

  1. 你不知道的JavaScript笔记----对象

    对象: 1.定义对象属性 属性描述符(也称为:数据描述符) Object.defineProperty(Object,PropertyName,{ value: 6, writable: true, ...

  2. 你不知道的javaScript笔记(7)

    异步:现在与将来 分块的程序 可以把JavaScript 程序写在单独的js 文件中,这个程序是由多个块组成的,这些块 中只有一个是现在执行,其余在捡来执行,最常见的块单位是函数. 例如: funct ...

  3. 你不知道的javaScript笔记(6)

    语法 语句表达式 句子是完整表达某个意思的一组词,由一个或多个短语组成,他们之间由标点符号或者连接词连接起来. 语句相当于句子,表达式相当于短语,运算符则相当于标点符号和连接词. JavaScript ...

  4. 你不知道的javaScript笔记(5)

    原生函数 常用的原生函数 String() Number() Boolean() Array() Object() Function() RegExp() Date() Error() Symbol( ...

  5. 你不知道的javaScript笔记(4)

    类型: JavaScript 有7种内置类型 空值 (null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(string) 对象(object) 符号(sy ...

  6. 你不知道的javaScript笔记(3)

    对象 对象可以通过两种形式定义: 声明形式和构造形式 声明形式语法: var myObj = {key:value} 构造形式语法: var myObj = new Object(); myObj.k ...

  7. 你不知道的javaScript笔记(1)

    规避冲突 function foo(){ function bar(a){ i = 3; console.log(a + i); } for ( var i=0; i < 10; i++){ b ...

  8. 你不知道的Javascript(上卷)读书笔记之一 ---- 作用域

    你不知道的Javascript(上卷)这本书在我看来是一本还不错的书籍,这本书用比较简洁的语言来描述Js的那些"坑",在这里写一些博客记录一下笔记以便消化吸收. 1 编译原理 在此 ...

  9. 你不知道的JavaScript上卷笔记

    你不知道的JavaScript上卷笔记 前言 You don't know JavaScript是github上一个系列文章   初看到这一标题的时候,感觉怎么老外也搞标题党,用这种冲突性比较强的题目 ...

随机推荐

  1. CentOS安装nginx方法命令教程

    1.依赖项和必要组件 yum install -y make cmake gcc gcc-c++ yum install -y pcre pcre-devel yum install -y zlib ...

  2. PHP file_put_contents() 函数

    file_put_contents() 函数把一个字符串写入文件中. 与依次调用 fopen(),fwrite() 以及 fclose() 功能一样. 语法如下 file_put_contents(f ...

  3. 【设计模式】template method(模板方法)-- 类行为型模式5.10

    1.意图 子类在不改变父类的算法结构的情况下,可以重定义算法的某些特定步骤 2.动机 模板方法用一些抽象的操作定义一个算法,子类重定义这些操作以提供具体的行为:步骤的顺序定了,但实现可以调整: 3.适 ...

  4. foreach的基本语法

    有一个布尔型循环是专门用来循环数组的.这个循环的基本语法就是foreach基本语法 foreach( 要循环的数组变量 as [键变量 =>] 值变量){ //循环的内容 } 这是一个固定用法, ...

  5. oracle学习篇四:多表查询

    -----------------产生笛卡儿积------------------------------------ select * from emp,dept; --不带条件时,记录数为14*4 ...

  6. Myeclipse中进行JUnit单元测试

    最近学习了在myeclipse中进行单元测试,写点东西总结总结. JUnit单元测试: 测试对象为一个类中的方法. juint不是javase中的部分,所以必须导入jar包,但是myeclipse自带 ...

  7. C++基础--字符串倒序输出

    (一)用基本的数组实现 #include "stdafx.h" #include <stdio.h> #include <string.h> int mai ...

  8. Polly一种.NET弹性和瞬态故障处理库(重试策略、断路器、超时、隔板隔离、缓存、回退、策略包装)

    下载地址:https://github.com/App-vNext/Polly 该库实现了七种恢复策略. 重试策略(Retry) 重试策略针对的前置条件是短暂的故障延迟且在短暂的延迟之后能够自我纠正. ...

  9. IT集中监控

    监控的从底层到上应该是: 一 数据采集层 二 数据处理层 三 数据展示层 监控需要和ITIL中定义的服务进行相当多的交互,例如监控会使用配置管理数据库CMDB来记录和读取数据,会将事件处理方式从知识库 ...

  10. springTask和Schedule学习

    Spring 4.x Task 和 Schedule 概述 http://www.jianshu.com/p/1778f6b9646e spring framework --- 定时任务(翻译官方文档 ...