我们到底能走多远系列(35)

扯淡:

  13年最后一个月了,你们在13年初的计划实现了吗?还来得及吗?

  请加油~

主题:

最近一直在写js,遇到了几个问题,可能初入门的时候都会遇到吧,总结下。

例子:
var x =9;
var fobj ={
x:1,
test:function(callback){
var x= 2;
callback();
}
}
function pp(){
var x = 3;
fobj.test(function(){
alert(this.x)//
})
}
pp();
上面这段代码打印出的是 9 ,可以看到test的调用者是fobj,可是在test中执行回调时callback();这调代码前面是空的。所以其实是有一个作为的全局调用了这个回调,所以,执行回调代码时的this则就是全局环境。
 
     总结一下:当方法被一个对象调用的时候:fobj.test(),那么this是绑定在fobj上的。
                    如果不是这样调用:callback() 那么this则绑定在全局变量上。
 
     回调函数中的this,最好不要使用,因为this指的是,调用函数的那个对象。
回调函数作为参数传入一个方法,我们就不能确定这个方法中的环境变量是怎样了的。
 
Function的bind方法:
var x =9;
var fobj ={
x:1,
test:function(callback){
var x= 2;
callback();
}
}
function pp(){
var x = 3;
fobj.test(function(){
alert(this.x)//
}.bind(fobj))
}
pp();
使用bind方法后输出为1,其中的this指向了fobj。
 
Array的forEach方法
在使用forEach方法的时候,也有类似的场景,这个方法提供了参数传入指定的上下文
例子:
var x = "test";
var ojb = {
x : "obj"
}
function pp(){
var t = [1,2,3,4];
t.forEach(function(value,index){
alert(this.x + value);
},ojb);
}
pp();
以上代码就指定了forEach中第一个参数匿名函数的上下文为ojb。
详细的参数规则和方法使用教程:摸我
 
循环回调函数问题:
例子:
for(var i=1;i<4;i++){
doCallBack(function(){
alert(i);//1,2,3
});
} function doCallBack(callback){
var x = "callback";
callback();
}
     上面的代码执行结果看似没有问题,在实际项目中,使用回调异步一些耗时工作,比如数据库的查询,写node的时候这种情况很多,那么会出现什么样的结果呢?
看下下面的模拟:
for(var i=1;i<4;i++){
doCallBack(function(){
setTimeout(function(){alert(i);},1000)//4,4,4
});
} function doCallBack(callback){
var x = "callback";
callback();
}
     全部打印4,导致这个发生的原因是因为回调函数中的耗时工作是异步的,也就是说第一次循环执行到doCallBack的时候,直接跳到for的末尾,然后开始第二次循环,一次类推,当循环达到i的最大值4的时候跳出循环,而延迟的工作开始了,这时候他们打印i,而这个i被加到了4,所以就有了全部打印4的结果。
 
先理解下js中的作用域链,比如下面的代码型式:
function A(){
var i =1;
function B(){
i =2;
...
}
}
function C(){...}
     B方法的作用域链就像这样 B内部 ->A内部 ->全局,也就是说方法内部的方法是可以引用到外部方法的变量的,如果这个B方法在C被调用,那么我们就实现C方法使用到了同级方法的作用域。其实我们就会认为这是一个闭包的行为。这样的作用域链机制,带来的副作用在前面提到的例子中展示了。
 
解决办法: 
for(var i=1;i<4;i++){
(function(x){
doCallBack(function(){
// alert(x)
setTimeout(function(){alert(x);},1000);//1,2,3
});
})(i)
} function doCallBack(callback){
callback();
}
     这里我们可以看到加了个匿名方法包在外面然后直接传入i,执行方法。还利用了这个i作为基本类型是按值传递的,所以在函数内部是一个复制的值,外部i的自增将不能改变内部函数的x的值了。
 
也可以写成这样:
for(var i=1;i<4;i++){
!function(x){
doCallBack(function(){
// alert(x)
setTimeout(function(){alert(x);},1000);//1,2,3
});
}(i)
} function doCallBack(callback){
callback();
}
用递归的办法:感受下
function doCallBack(x){
if(x<=1){
return 1;
}else{
setTimeout(function(){alert(x);},1000);//4,3,2
return doCallBack(x-1);
} }
doCallBack(4)
实际应用中,遇到引用类型的时候,展示使用里很土的办法先解决一下
代码类似:(3次循环,修改成下面代码)
var rstScoreMsg0 = {
score : scores[0],
username : uids[0],
expLoser : expLoser,
expWinner : expWinner,
uid : 0
};
var rstScoreMsg1 = {
score : scores[1],
username : uids[1],
expLoser : expLoser,
expWinner : expWinner,
uid : 0
};
var rstScoreMsg2 = {
score : scores[2],
username : uids[2],
expLoser : expLoser,
expWinner : expWinner,
uid : 0
}; recordUser(rstScoreMsg0);
recordUser(rstScoreMsg1);
recordUser(rstScoreMsg2);
 
理论上,通过对象复制也是可行的。
 
 
 
 
 

让我们继续前行

----------------------------------------------------------------------

努力不一定成功,但不努力肯定不会成功。

js中this和回调方法循环-我们到底能走多远系列(35)的更多相关文章

  1. 利用spring AOP 和注解实现方法中查cache-我们到底能走多远系列(46)

    主题:这份代码是开发中常见的代码,查询数据库某个主表的数据,为了提高性能,做一次缓存,每次调用时先拿缓存数据,有则直接返回,没有才向数据库查数据,降低数据库压力. public Merchant lo ...

  2. 【温故知新】——原生js中常用的四种循环方式

    一.引言 本文主要是利用一个例子,讲一下原生js中常用的四种循环方式的使用与区别: 实现效果: 在网页中弹出框输入0   网页输出“欢迎下次光临” 在网页中弹出框输入1   网页输出“查询中……” 在 ...

  3. node.js中的url.parse方法使用说明

    node.js中的url.parse方法使用说明:https://blog.csdn.net/swimming_in_it_/article/details/77439975 版权声明:本文为博主原创 ...

  4. javascript基础入门之js中的结构分支与循环语句

    javascript基础入门之js中的结构分支与循环语句 程序的结构①顺序结构:自上而下:②选择(分支)结构:多条路径,根据不同的条件,只执行其中一个:③循环结构:重复某些代码④配合特定的语句实现选择 ...

  5. JS中的对象和方法简单剖析

    众所周知,在js中对象就是精髓,不理解对象就是不理解js. 那么什么事js中的对象呢? 在js中,几乎一切皆对象: Boolean ,String,Number可以是对象(或者说原生数据被认作对象): ...

  6. 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?

    https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...

  7. js中数组去重的方法

    在实际工作或面试中,我们经常会遇到"数组去重"问题,接下来就是使用js实现的数组去重的多种方法: 1.借助ES6提供的Set结构 var arr = [1,1,2,2,3,3,4, ...

  8. JS中 call() 与apply 方法

    1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call ...

  9. JS中定义类的方法

    JS中定义类的方式有很多种: 1.工厂方式    function Car(){     var ocar = new Object;     ocar.color = "blue" ...

随机推荐

  1. 如何解决链入js,innerHTML中文乱码问题呢?

    描述:发生在做suhuotong网站的时候,添加在线客服代码的时候三个地方1.将js以UTF-8无BOM编码:VS修改或者使用NotePad++修改2.<meta http-equiv=&quo ...

  2. GUID

    前言 全局唯一标识符,简称GUID(发音为 /ˈɡuːɪd/或/ˈɡwɪd/),是一种由算法生成的唯一标识,通常表示成32个16进制数字(0-9,A-F)组成的字符串,如:{21EC2020-3AEA ...

  3. java之trycatchfinally代码块与return,throw的执行顺序的探索

    时光荏苒,转眼间毕业都半年了,java编程也五个月了.写代码的过程中,会经常遇到解决代码抛异常的情况.平时只注重完成功能,也没太注意try_catch_finally的内在执行顺序,只知道表面的现象: ...

  4. 两个activity之间传递数据用startActivityForResult方法。

    package com.example.testactivityresquest; import android.app.Activity; import android.content.Intent ...

  5. 5.2使用select,poll

    5.2 使用select,poll   // CPU占用率低,适用于很多简单场合 参考:UNIX环境高级编程 I/O多路转接 监测多个文件,只要有某一个文件可读/可写/异常或超时,即返回 int se ...

  6. Java:String、StringBuffer和StringBuilder的区别

    1 String String:字符串常量,字符串长度不可变.Java中String是immutable(不可变)的. String类的包含如下定义: /** The value is used fo ...

  7. IT公司100题-1-二叉树转换为双链表

    问题描述: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向. 10   /   \  6      14/  \    /   \4   8 1 ...

  8. DB2事务日志已满的解决方法

    DB2命令终端输入: db2 update db cfg for <dbname> using LOGPRIMARY 50 db2 update db cfg for <dbname ...

  9. 在OpenShift云空间上部署java web应用

    在使用之前先来介绍下OpenShift空间 OpenShift是由红帽推出逇一款面向开源开发人员开放的平台即服务(PaaS). OpenShift通过为开发人员提供在语言.框架和云上的更多的选择,使开 ...

  10. Yslow&PageSpeed– 诊断各种缓慢症状

    Google的PageSpeed和yahoo的yslow是各位不可少的前端工具(同样也都是firebug的插件,安装了firebug之后才可以拥有她们),当各位无法用三寸不烂之舌收拾产品和各种大佬的时 ...