javascript读取内存中请求体内容,并且能console.log 内存()出来该怎么实现

转自:http://www.jb51.net/article/30469.htm
javascript的console.log()用法
console.log 原先是 F...
一、显示信息的命令
Firebug内置一个console对象,提供5种方法,用来显示信息。
最简单的方法是console.log(),可以用来取代alert()或document.write()。...
当你使用console.log()函数时,下面的firebug一定要打开,不然这函数在用firefox运行时无效且影响正常程序,如果用IE打开,将会出错。
第一个参数可以是一个包含格式化占位...
用console.log替代alert alert输出内容会暂停程序 用控制台输出相对来说比较方便
按f12就可以轻松的打开控制台
大家可以看到控制台里面有一首诗还有其它信息,如果想清空控制台...
一、console.log()简介对于JavaScript程序的调试,相比于alert(),使用console.log()是一种更好的方式,原因在于:alert()函数会阻断JavaScript程序的...
对应WEB程序员,console.log 可以说是神器,极大地方便了程序开发。程序猿:学习了,用Console写日志比alert方便多了。
console.log(object[, object, ...
我们在做js调试的时候使用
alert 可以显示信息,调试程序,alert
弹出窗口会中断程序, 如果要在循环中显示信息,手点击关闭窗口都累死。而且 alert 显示对象永远显示为[object ...
js console.log 打印 对像 数组 详解
console.log是什么东西,其实就是一个打印js数组和对像的函数而已,就像是php的print_r,var_dump。co...
通过使用Log4net框架,创建按日期分类输出日志在文本文件的示例程序。
1 使用log4net框架提供的日志功能,进行系统的日志管理。
敲了将近两周的前端代码,为了页面调试方便,有的时候用console.log,有的时候用alert,console.log是在控制台中打出日志,alert是在界面上弹框呈现,在页面调...
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)二 Console.log 总结
如果你js没到一个境界,我就算教你调试bug,破解一些插件之类的,你也根本不知道我在做什么。我的...
console调试javascript
对于JavaScript程序的调试,相比于alert(),使用console.log()是一种更好的方式,原因在于:alert()函数会阻断JavaScript程序的执行,从而造成副作用;而conso...
非营养贴!
有没有调试JS还在用alert的小朋友?
尝试使用console吧,IE/Chrome都支持的,非常好用!
1.输出变量!
console.log("start");
对于JavaScript程序的调试,相比于alert(),使用console.log()是一种更好的方式,原因在于:alert()函数会阻断JavaScript程序的执行,从而造成副作用;而conso...
对于JavaScript程序的调试,相比于alert(),使用console.log()是一种更好的方式,原因在于:alert()函数会阻断JavaScript程序的执行,从而造成副作用;而conso...
对于JavaScript程序的调试,相比于alert(),使用console.log()是一种更好的方式,原因在于:alert()函数会阻断JavaScript程序的执行,从而造成副作用;而conso...
浏览器控制台输出图片,彩色字体,文字
if (window.console)
console.log还支持格式化输出:%s(字符串)%d、%i(整数)%f(浮点数)%c(CSS样式)
console.log("%c%s","color: backgr...
当我们的PHP程序Debug时,比较常用的方式是将变量的信息打印到浏览器中,例如这样:
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
第一章 JavaScript (基础)
第二章 JavaScript(高级)javascript读取内存中请求体内容,并且能console.log()出来该怎么实现
javascript读取内存中请求体内容,并且能console.log()出来该怎么实现
小白实在不懂了,主要用来读取截取到的post请求的请求体中的内容,都快急哭了!大家帮帮忙附上两张图
最佳推荐答案
想查看post请求的请求体中的内容,控制台的console,点击post的请求文件.log是不行的,这样只能看到DOM结构的数据,如果想看到实体数据,需要切换到“Network”选项(这里以Chrome浏览器为例)
版式: | 炫彩版 | 12-29 18:21从 JS Event Loop 机制看 Vue 中 nextTick 的实现原理 - 研发管理 - ITeye资讯
相关知识库:
引用来源:
作者:
作为一名前端,一直以来以精通Javascript为目标。其实说实话精通真的挺难,不是你记住全部的API就算是精通。
JavaScript的知识非常零散而庞杂,很多情况下上周学习的知识下周或是下个月就会忘记,给人的感觉就是好难学,怎么一直没进步呢?我们不能仅限于语言本身,我们要透过语法看到深层次的运行机制。掌握了Javascript运行机制,就好比学武术,大神级别都讲究“无招胜有招”。懂得了机制就可以举一反三,灵活运用。
事件循环机制(Event Loop),则是理解运行机制最关键的一个点。我们先抛出一个面试题:
setTimeout(function() {
console.log(1)
new Promise(function executor(resolve) {
console.log(2);
for( var i=0 ; i&10000 ; i++ ) {
i == 9999 && resolve();
console.log(3);
}).then(function() {
console.log(4);
console.log(5);
先思考,这段代码会输出什么?
单线程的JavaScript
JavaScript是单线程的,我想大家都不会怀疑吧。那什么是单线程?
当初我对“js是单线程”的理解仅限于js的代码是一行一行执行的,不会出现同时执行两行的代码的情况,可是这个理解是太浅显,遇到异步请求就懵逼了,怎么不按我的想法走呢?还用说想法有问题呗。
所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个。JS运行在浏览器中,是单线程的,每个window一个JS线程。
第一个问题,为啥要是单线程,多线程不好吗?减轻cpu的压力。现在如果有两个线程,一个线程修改页面某一个dom元素,正巧另一个线程将这个元素给删除了。这不是混乱了么。所以单线程是有原因的。
那你又有疑问了,既然是单线程的,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码。那不行啊,我们总不能一直等着啊,前端需要调用后端接口取数据,这个过程是需要响应时间的,那执行这个代码的时候浏览器也等着?答案是否定的。
其实还有其他很多类线程(应该叫做任务队列),比如进行ajax请求、监控用户事件、定时器、读写文件的线程(例如在NodeJS中)等等。这些我们称之为异步事件,当异步事件发生时,将他们放入执行队列,等待当前代码执行完成。就不会长时间阻塞主线程。等主线程的代码执行完毕,然后再读取任务队列,返回主线程继续处理。如此循环这就是事件循环机制。
总结一下:
我们可以认为某个同域浏览器上下文中 JavaScript 只有一个主线程、函数调用栈以及多个任务队列。
主线程会依次执行代码,当遇到函数时,会先将函数入栈,函数运行完毕后再将该函数出栈,直到所有代码执行完毕。
当函数调用栈为空时,即会根据事件循环(Event Loop)机制来从任务队列中提取出待执行的回调并执行,执行的过程同样会利用函数栈。
所有同属一个的窗体都共享一个事件循环,所以它们可以同步交流。不同窗体之间相互独立,互不干扰。
你如果想彻底研究清楚事件模型,那还需要了解如下知识:
Javascript的队列数据结构
Javascript的执行上下文
函数调用栈(call stack)
我们会分为两节来学习,队列数据结构为一节,执行上下文和函数调用栈合在一起为一节。
Javascript的内存空间
队列数据结构
我们知道Javascript中有两种基本的种数据结构堆(heap)和栈(stack),还有一个队列(queue),并不是严格意义上的数据结构。
栈数据结构
在我们平时的工作过程中我们写javascript代码并不关心数据结构,但是它确实彻底理解某些运行机制的必不可少的部分。
JavaScript中并没有严格的去区分栈内存与堆内存。我们平时基本都认为JavaScript的所有数据(变量、函数)都保存在堆内存中。但是在某些场景,我们仍然需要基于堆栈数据结构的思维(看好这里是思维)来看待,比如JavaScript的执行上下文。
要简单理解栈的存取方式,我们可以通过类比乒乓球盒子来分析。如下图左侧。
我们用栈存取数据的方式类比成乒乓球的存放方式,处于盒子中最顶层的乒乓球5,它一定是最后被放进去,但可以最先被使用。而我们想要使用底层的乒乓球1,就必须将上面的4个乒乓球取出来,让乒乓球1处于盒子顶层。这就是栈空间先进后出,后进先出的特点。
堆数据结构
堆数据的存取数据的方式和与书架与书非常相似。
书架上放满了不同的书,我们只要知道书的名字我们就可以很方便的取出,而不用像从乒乓球盒子里取乒乓一样,非得将上面的所有乒乓球拿出来才能取到中间的某一个乒乓球。在JSON格式的数据中,我们存储的key-value是可以无序的,我们并不关心顺序,我只要通过key取出value即可。
在JavaScript中,理解队列数据结构的目的主要是为了理解事件循环(Event Loop)的机制。在后续的章节中我会详细分析事件循环机制。
队列是一种先进先出(FIFO)的数据结构。正如排队过安检一样,排在队伍前面的人一定是最先过检的人。用以下的图示可以清楚的理解队列的原理。
执行上下文and函数调用栈
这节我们稍微研究一下JavaScript中最基本的部分——执行上下文(Execution Context), 读完后,你应该清楚了解释器做了什么,为什么函数和变量能在声明前使用以及他们的值是如何决定的。
每当控制器转到可执行代码的时候,就会进入一个执行上下文。执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。JavaScript中的运行环境一般有两种:
全局环境:JavaScript代码运行起来会首先进入该环境
函数环境:当函数被调用执行时,会进入当前函数中执行代码
其实这里还应该有一个eval环境,不推荐用eval,今天也就不谈。
因此在一个JavaScript程序中,必定会产生多个执行上下文,JavaScript引擎会以栈的方式来处理它们,我们称其为函数调用栈(call stack)。
栈底永远都是全局上下文,而栈顶就是当前正在执行的上下文。
遇到以上两种情况,都会生成一个执行上下文,放入栈中,而处于栈顶的上下文执行完毕之后,就会自动出栈。
为了更加清晰的理解这个过程,根据下面的例子,结合图示给大家展示。
执行上下文可以理解为函数执行的环境,每一个函数执行时,都会给对应的函数创建这样一个执行环境。
modify.js
var name= 'dsx';
function modifyName() {
var secondName= 'gwj';
function swapName() {
var temp = secondN
secondName=
swapName();
changeColor();
我们用ECStack来表示处理执行上下文组的堆栈。我们很容易知道,第一步,首先是全局上下文入栈。
全局入栈后,开始执行可执行代码,直到遇到了modifyName(),这一句激活函数modifyName创建它自己的执行上下文,因此第二步就是modifyName的执行上下文入栈。
modifyName入栈之后,继续执行函数内部可执行代码,遇到swapName()之后又激活了swapName执行上下文。因此第三步是swapName的执行上下文入栈。
在swapName的内部再没有遇到其他能生成执行上下文的代码,因此这段代码顺利执行完毕,swapName的上下文从栈中弹出。
swapName的执行上下文出栈后,继续执行modifyName其他可执行代码,也没有再遇到其他执行上下文,顺利执行完毕之后出栈。这样,ECStack中就只身下全局上下文了。
全局上下文在浏览器窗口关闭后出栈。
注意: 第一、函数中,遇到return能直接终止可执行代码的执行,因此会直接将当前上下文弹出栈。 第二、不要把执行上下文和作用域链混为一谈
如上我们演示了整个modif.js的执行过程。总结一下:
单线程,依次自顶而下的执行,遇到函数就会创建函数执行上下文,并入栈
同步执行,只有栈顶的上下文处于执行中,其他上下文需要等待
全局上下文只有唯一的一个,它在浏览器关闭时出栈
函数的执行上下文的个数没有限制
每次某个函数被调用,就会有个新的执行上下文为其创建,即使是调用的自身函数,也是如此。
事件循环
现在我们知道JavaScript的单线程,以及这个线程中拥有唯一的一个事件循环机制。那什么事件循环机制是什么?且看下文分析。
JavaScript代码的执行过程中,除了依靠函数调用栈来搞定函数的执行顺序外,还依靠任务队列(task queue)来搞定另外一些代码的执行。
根据上面的分析,任务队列的特点是先进先出。
一个js文件里事件循环只有一个,但是任务队列可以有多个。任务队列又可以分为macro-task(task)与micro-task(job)。
macro-task(task)包括:
setTimeout/setInterval
setImmediate
I/O操作
UI rendering
micro-task(job)包括:
process.nextTick
Promise
Object.observe(已废弃)
MutationObserver(html5新特性)
浏览器中新标准中的事件循环机制与nodejs类似,其中会介绍到几个nodejs有,但是浏览器中没有的API,大家只需要了解就好。比如process.nextTick,setImmediate
我们称他们为事件源, 事件源作为任务分发器,他们的回调函数才是被分发到任务队列,而本身会立即执行。
例如,setTimeout第一个参数被分发到任务队列,Promise的then方法的回调函数被分发到任务队列(catch方法同理)。
不同源的事件被分发到不同的任务队列,其中setTimeout和setInterval属于同源
整体代码开始第一次循环。全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的job。当所有可执行的job执行完毕之后。循环再次从task开始,找到其中一个任务队列执行完毕,然后再执行所有的job,这样一直循环下去。
无论是task还是job,都是通过函数调用栈来完成。
这个时候我们是不是有一个大发现,除了首次整体代码的执行,其他的都有规律,先执行task任务队列,再执行所有的job并清空job队列。再执行task--job--task--job......,往复循环直到没有可执行代码。
那我们可不可以这么理解,第一次script代码的执行也算是一个task任务呢,如果这么理解那整个事件循环就很容易理解了。
来走一个栗子:
console.log(1);
Promise(function(resolve){
console.log(2);
resolve();
}).then(function(){
console.log(3)
setTimeout(function(){
console.log(4);
process.nextTick(function(){
console.log(5);
Promise(function(resolve){
console.log(6);
}).then(function(){
console.log(7)
process.nextTick(function(){
console.log(8)
setImmediate(function(){
console.log(9);
Promise(function(resolve){
console.log(10);
}).then(function(){
console.log(11)
process.nextTick(function(){
console.log(12);
})
一下子写了这么多,是不是感觉有点复杂啊,不过没关系,我们一步一步来分析。
第一步,开始执行代码,global入栈,执行到第一个console.log(1),直接输出1。
第二步、执行遇到了Peomise,Promise构造函数的回调函数是同步执行,直接输出2。它的then方法才是任务源,将会分发一个job任务。
Promise(function(resolve){
console.log(2);
resolve();
}).then(function(){
console.log(3)
第三步、执行到setTimeout,作为task任务分发源,分发一个任务出去。
setTimeout(function(){
console.log(4);
process.nextTick(function(){
console.log(5);
Promise(function(resolve){
console.log(6);
}).then(function(){
console.log(7)
第四步、执行遇到process.nextTick, 一个job任务分发器,分发一个job任务。
process.nextTick(function(){
console.log(8)
第五步、执行遇到setImmediate, 一个task任务分发器,分发一个task任务到任务队列。并且会在setTimeout的任务队列之后执行。
setImmediate(function(){
console.log(9);
Promise(function(resolve){
console.log(10);
}).then(function(){
console.log(11)
process.nextTick(function(){
console.log(12);
这样script代码的第一轮执行完毕,在执行的过程中会遇到不同的任务分发器,分发到对应的任务队列。接下来将会执行所有的job队列的任务。
注意:nextTick任务队列会比Promise的队列先执行(别问为什么,我也不知道)
这阶段会依次输出 8 3。
执行完所有的job任务后,就会循环下一次,从task开始,根据图示,会先执行Time_out1队列。
task任务的执行也是要借助函数栈来完成,也就是说回到主线程。
会先依次输出4和6,然后依次分发nextTick2和promise_then2两个job任务。
第一个task任务执行完不会立即执行其他task任务,会执行刚才被分发的job任务
在这个过程中会依次输出5和7
现在就剩下一个task任务setIm1,按照同样的方式进行再次循环 。示意图如下:
以上阶段会依次输出9和10。
最后执行job任务,依次输出12和11。
完事,这个事件循环就完成了,我想是很清楚了。最终的输出结果是:
1,2,8,3,4,6,5,7,9,10,12,11
最后我们用node执行一下我们写的这个例子。结果如下:
Vue中的nextTick()实现原理
new Vue({
el: '#app',
mounted: function () {
this.get()
methods: {
get: function () {
this.$http.get('/api/article').then(function (res) {
this.list = res.data.data.list
// this.$refs.list引用了ul元素,我想把第一个li颜色变为红色
this.$refs.list.getElementsByTagName('li')[0].style.color = 'red'
})
我在获取到数据后赋值给data对象的list属性,然后我想引用ul元素找到第一个li把它的颜色变为红色,但是事实上,这个要报错的。我们知道,在执行这句话时,ul下面并没有li,也就是说刚刚进行的赋值操作,当前并没有引起视图层的更新。
因为Vue的数据驱动视图更新,是异步的,即修改数据的当下,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
因此,在这样的情况下,vue给我们提供了$nextTick方法,如果我们想对未来更新后的视图进行操作,我们只需要把要执行的函数传递给this.$nextTick方法,vue在更新完视图后就会执行我们的函数帮我们做事情。
$nextTick()原理:
Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MutationObserver,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。
看过上一个chat()的同学应该有了解,vue里面有一个watcher,用于观察数据的变化,数据有变化就会更新dom。
但是vue并不是每次数据改变都会立即触发更新dom,而是将这些操作都缓存在一个队列,如果同一个 watcher 被多次触发,只会一次推入到队列中。这样可以避免不必要的重复计算和 DOM 操作,提升性能。
那什么时候更新DOM呢?在下一个事件循环“tick”中,Vue 刷新队列并执行,统一执行(已去重的)dom的更新操作。
在前面我们花了大量篇幅来介绍javascript的事件循环机制,应该知道事件循环中有两种任务队列, macro-task(task) 和 micro-task(job)。
引擎在每个 task 执行完毕,从队列中取下一个 task 来执行之前,会先执行完所有 micro-task(job)队列中的 job。
setTimeout 任务源会分配回调到一个新的 task 中执行,而 Promise 的 then、MutationObserver 的回调都会被安排到一个新的 job 中执行,会比 setTimeout 产生的 task 先执行。
想要要创建一个新的 job,优先使用 Promise,如果浏览器不支持,再尝试 MutationObserver。实在不行,只能用 setTimeout 创建 task 了。
为啥要用 job?根据HTML Standard,在每个 task 运行完以后,UI 都会重渲染,那么在 job 中就完成数据更新,当前 task 结束就可以得到最新的 UI 了。反之如果新建一个 task 来做数据更新,那么渲染就会进行两次。
总结$nextTick触发的时机:
同一事件循环中的代码执行完毕 -& DOM 更新 -& nextTick callback触发
$nextTick源码:
//首先,这个函数是采用了一个单利模式还是什么创建的一个闭包函数
nextTick = (function(){
// 缓存函数的数组
var callbacks = [];
// 是否正在执行
var pending =
// 保存着要执行的函数
var timerF
})()
首先定义一些变量,供后面调用。接下来是一个函数:
//执行并且清空所有的回调列表
function nextTickHandler() {
//拷贝出函数数组副本
const copies = callbacks.slice(0);
//把函数数组清空
callbacks.length = 0;
//依次执行函数
for (let i = 0; i & copies. i++) {
copies[i]();
}
这个函数就是$nextTick内实际调用的函数。
接下来,是vue分了三种情况来延迟调用以上这个函数,因为$nextTick目的就是把传进来的函数延迟到dom更新后再使用,所以这里依次优雅降序的使用js的方法来做到这一点。
利用promise.then延迟调用
if (typeof Promise !== 'undefined' && isNative(Promise)) {
var p = Promise.resolve();
var logError = function (err) { console.error(err); };
timerFunc = function () {
p.then(nextTickHandler).catch(logError);
// 在部分 iOS 系统下的 UIWebViews 中,Promise.then 可能并不会被清空,因此我们需要添加额外操作以触发
if (isIOS) { setTimeout(noop); }
};
如果浏览器支持Promise,那么就用Promise.then的方式来延迟函数调用,Promise.then方法可以将函数延迟到当前函数调用栈最末端,也就是函数调用栈最后调用该函数。从而做到延迟。
MutationObserver 监听变化
else if (typeof MutationObserver !== 'undefined' && (
isNative(MutationObserver) ||
MutationObserver.toString() === '[object MutationObserverConstructor]'
/ 当 Promise 不可用时候使用 MutationObserver
var counter = 1;
var observer = new MutationObserver(nextTickHandler);
var textNode = document.createTextNode(String(counter));
observer.observe(textNode, {
characterData: true
timerFunc = function () {
counter = (counter + 1) % 2;
textNode.data = String(counter);
}
MutationObserver是h5新加的一个功能,其功能是监听dom节点的变动,在所有dom变动完成后,执行回调函数。
具体有一下几点变动的监听:
childList:子元素的变动
attributes:属性的变动
characterData:节点内容或节点文本的变动
subtree:所有下属节点(包括子节点和子节点的子节点)的变动
可以看出,先创建了一个文本节点,来改变文本节点的内容来触发的变动,因为我们在数据模型更新后,将会引起dom节点重新渲染,所以,我们加了这样一个变动监听,用一个文本节点的变动触发监听,等所有dom渲染完后,执行函数,达到我们延迟的效果。
setTimeout延迟器
timerFunc = function () {
setTimeout(nextTickHandler, 0);
}
这个很简单哈。利用setTimeout的延迟原理,setTimeout(func, 0)会将func函数延迟到下一次函数调用栈的开始,也就是当前函数执行完毕后再执行该函数,因此完成了延迟功能。
但是我们看到的$nextTick是一个函数啊,这里就是一个自执行函数,并不是一个函数啊,没错我们还需要返回一个闭包函数才可以。往下看:
return function queueNextTick (cb, ctx) {
callbacks.push(function () {
if (cb) { cb.call(ctx); }
if (_resolve) { _resolve(ctx); }
// 如果没有函数队列在执行才执行
if (!pending) {
timerFunc();
// promise化
// 如果没有传入回调,则表示以异步方式调用
if (!cb && typeof Promise !== 'undefined') {
console.log('进来了')
return new Promise(function (resolve) {
_resolve =
}
这个return的函数就是我们实际使用的闭包函数,每一次调用$nextTick函数,都会向callbacks这个函数数组入栈。然后监听当前是否正在执行,如果没有,执行函数。下面一个if是promise化,如果没有传入回调,则表示以异步方式调用。
现在 Vue()的 nextTick 实现移除了 MutationObserver 的方式(兼容性原因),取而代之的是使用 MessageChannel。
并且加入了setImmediate。
有兴趣的同学可以继续去学习,原理我们已经说的很明白。源码。
相关资源推荐}

我要回帖

更多关于 console.log 内存 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信