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. JavaWeb技术

    1.简介 Java Web是用Java技术来解决相关web互联网领域的技术总和.web包括:web服务器和web客户端两部分.Java在客户端的应用有java applet,不过使用得很少,Java在 ...

  2. 00字体图标iconfont的制作与使用--阿里矢量图库

    一.iconfont的使用范围 在工作当中,经常会用到嵌在元素里的小图标 在这种情况下,如果使用<img>标签或者用作背景图片,也能实现这种效果.但是如果这么做的话,就必须把图片一个个切下 ...

  3. 【Android】5.0 第一个工程学习——应用名称和图标修改、增加Buton控件、Toast信息提示

    1.0 搞了很多天,eclipse只能开发Android6.0以前的版本,可能是因为谷歌不再针对eclipse更新了,在虚拟机Android6.0以上版本都无法构建,所以转到Android Studi ...

  4. PHP性能检测与优化—XHProf 安装

    PHP性能检测与优化—XHProf 安装 XHProf是facebook开源出来的一个php轻量级的性能分析工具,跟Xdebug类似,但性能开销更低,还可以用在生产环境中,也可以由程序开关来控制是否进 ...

  5. maven---Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.12.4

    Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.12.4 Failure to transfer or ...

  6. shell定时采集数据到HDFS

    上线的网站每天都会产生日志数据.假如有这样的需求:要求在凌晨 24 点开始操作前一天产生的日志文件,准实时上传至 HDFS 集群上. 该如何实现?实现后能否实现周期性上传需求?如何定时? Linux ...

  7. java:反射机制

    Java反射机制及IoC原理:https://www.cnblogs.com/Eason-S/p/5851078.html Java中反射机制详解:https://www.cnblogs.com/wh ...

  8. js如何完整的显示较长的数字

    试试下面一行吧 Math.pow(10, 99).toLocaleString().split(',').join('') toLocaleString([character]) 方法会将其对象转换成 ...

  9. vue项目运行报错:Module bulid failed: Error: Node Sass does not yet support your current environment

    出错起因:      从GitLab clone项目 --> 用 npm install 命令下载依赖包 --> #npm run dev,报错 错误截图: 解决方法:   思路:单独 i ...

  10. Sendip 命令行发包工具,支持IP、TCP、UDP等

    Sendip是一个linux平台的命令行发数据包工具,目前(2018年2月)支持的协议有ipv4.ipv6.icmp.tcp.udp.bgp.rip.ntp,作者表示其他协议将会后面支持,当他有空写的 ...