首页 文章 精选 留言 我的

精选列表

搜索[JavaScript库],共10000篇文章
优秀的个人博客,低调大师

JavaScript中关于this关键字的魔幻现实 一篇文章搞懂他

不得不承认JS中存在一些“历史的遗产”,比如基于全局变量的编程模型。 如果写一个函数,如: function test(name){ var namex = name console.log(this.namex) } test('jack') 方法调用之后,this.namex=undefined,为何呢?因为此处的this是全局对象window,这就令人比较头大。 不过别着急,慢慢往下看,关于this还有很多魔幻的现实,我们来一一解锁。 1、完整的函数调用 还是上面的代码,其实他的完整调用写法是这样的: function test(name){ var namex = name console.log(this.namex) } test.call(undefined, 'jack') test是一个函数对象--即Function对象,Function.prototype有call方法。call()会有两个参数,第一个参数是this上下文对象,第二个参数是函数入参列表。 如果call()传入的this上下文是undefined或null,那么window对象将成为默认的this上下文 2、对象中的this const obj = { name: 'Jack', greet: function() { console.log(this.name) } } obj.greet() //简写调用 obj.greet.call(obj) //完整调用 obj.greet()中的this无疑就是obj对象 3、对象方法中嵌套函数的this 对2中的代码进行修改: const obj = { name: 'Jack', greet: function() { retufn function(){console.log(this.name)} } } obj.greet()() //输出null 需要注意的是嵌套函数中的this依然是window,为什么呢?可以拆分来看: var greet = obj.greet() greet() // = greet.call(undefined) 嵌套函数被调用的时候,真实的调用者上下文是undefined,也就是window 4、原型与this function Clt() { } Clt.prototype.x = 10 Clt.prototype.test = function () { console.log(this) this.y = this.x + 1 } let bean = new Clt() bean.test(); console.log(bean.y) test方法中输出的this是一个Clt对象。 这里需要引入一个新的概念:构造器函数。 new关键字就是构造器函数,它的作用是: 一旦函数被new来调用,就会创建一个链接到该函数的prototype属性的新对象,同时this会被绑定到那个新对象上 理解了构造器函数,我们就理解了原型与this的关系了,因为new会重新指定this上下文 5、箭头函数与this ECMAScript6出现了箭头函数的用法,关于箭头函数中的this,需要先记住一句话: 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。 看代码(引自阮一峰老师的教程:https://es6.ruanyifeng.com/#docs/function#%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0): function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 42 此处的this指向了foo的this上下文,即定义时的this对象。 箭头函数与非箭头函数的this区别: function Timer() { this.s1 = 0; this.s2 = 0; // 箭头函数 setInterval(() => this.s1++, 1000); // 普通函数 setInterval(function () { this.s2++; }, 1000); } var timer = new Timer(); setTimeout(() => console.log('s1: ', timer.s1), 3100); setTimeout(() => console.log('s2: ', timer.s2), 3100); // s1: 3 // s2: 0 箭头函数的this指向了定义时所在对象的this;非箭头函数的this指向了运行时的作用域,即全局域window this的指向固定化,也算是解决了一些历史旧账,无疑带来的很大好处,比如封装调用: var handler = { id: '123456', init: function() { document.addEventListener('click', event => this.doSomething(event.type), false); }, doSomething: function(type) { console.log('Handling ' + type + ' for ' + this.id); } }; 一个嵌套的例子: function foo() { return () => { return () => { return () => { console.log('id:', this.id); }; }; }; } var f = foo.call({id: 1}); var t1 = f.call({id: 2})()(); // id: 1 var t2 = f().call({id: 3})(); // id: 1 var t3 = f()().call({id: 4}); // id: 1 最里层的this也绑定到了定义时所在对象的—即foo的this 总结 ECMAScript6的箭头函数也算是解决了一些历史问题。不过正如HTML5离不开HTML4一样,因为只有保持了继承与兼容,新技术的推广才会更加的迅速。 享受语言新特性之余,也要搞清楚旧版本的一些细节,这有助于更全面的掌握知识。 希望这篇文章对您有用!

优秀的个人博客,低调大师

通过阶乘的例子,练习在JavaScript, Scala和ABAP里实现尾递归(Tail Recursion)

Before we start to research tail recursion, let’s first have a look at the normal recursion. A simple factorial implementation by recursion: function factorial(n){ if(n ===1) { return 1; } return n *factorial(n -1); } Let N = 5, see how new stack frame is created for each time of recursive call: We have two stack frames now, one stores the context when n = 5, and the topmost one for current calculation: n = 4 Now since n equals to 1, we stop recursion. The current stack frame ( n = 1 ) will be poped up, the frame under it will be activated and become the topmost frame, with calculated result 1 passed into. key note for normal recursion: during recursion, every generated stack frame is needed and could not e destroyed until the final result is calculated. The calculation is actually not started until the recursion reaches the end ( the condition n === 1 fulfills ). If N is a big integer, it will lead to huge number of stack frames and finally the “stack overflow” or “out of memory” is inevitable. tail recursion Source code below: function tailFactorial(n, total) { if(n ===1) return total; return tailFactorial(n -1, n * total); } function factorial2(n) { return tailFactorial(n,1); } There are two biggest differences compared with normal recursion: (1) A new internal function tailFactorial is introduced here. (2) The calculation is actually now spread within every recursive stack frame. Each frame finishes one part of calculation and pass the current result to the next frame. Once the current stack frame finishes its task, it is actually not needed any more. And thus for example the model browser can then do some optimization on those useless stack frames. Observe the stack frame for tail recursion step by step: stack popped up: When N = 20, the tail recursion has a far better performance than the normal recursion: Update 2016-01-11 Tail recursion implementation via Scala: The interesting thing is, after the Scala code is compiled into Java Byte code, compiler will eliminate the recursion automatically: Tail Recursion in ABAP First this is the normal recursion: REPORT zrecursion. START-OF-SELECTION. DATA: lv_result TYPE int4. PERFORM fac USING 6 CHANGING lv_result. WRITE: / lv_result. FORM fac USING iv_n TYPE int4 CHANGING cv_result TYPE int4. DATA: lv_n TYPE i. cv_result = lv_n = iv_n. lv_n = lv_n - 1. IF lv_n > 1. PERFORM fac USING lv_n CHANGING cv_result. ENDIF. IF lv_n = 1. cv_result = cv_result * lv_n. ELSE. cv_result = cv_result * iv_n. ENDIF. ENDFORM. And here comes tail recursion version: REPORT ztail. START-OF-SELECTION. DATA: lv_result TYPE int4. PERFORM fac USING 5 1 CHANGING lv_result. WRITE: / lv_result. FORM fac USING iv_n TYPE int4 iv_acc TYPE int4 CHANGING cv_result TYPE int4. DATA: lv_n TYPE i, lv_accumulate TYPE i. IF iv_n < 1. cv_result = 1. ELSEIF iv_n = 1. cv_result = iv_acc * iv_n. ELSEIF iv_n > 1. lv_n = iv_n - 1. lv_accumulate = iv_acc * iv_n. PERFORM fac USING lv_n lv_accumulate CHANGING cv_result. ENDIF. ENDFORM. 本文来自云栖社区合作伙伴“汪子熙”,了解相关信息可以关注微信公众号"汪子熙"。

优秀的个人博客,低调大师

JavaScript ES6 Fetch API时需要注意的一个Cookie问题

When I am doing a test of comparison between Stateful and Stateless BSP application ( mentioned in blog Stateless and Stateful – Different behavior in application side ), I meet with a strange issue. The conclusion is stateful BSP application will handle request sequentially. Suppose in client I send two request A and B to server. Request A takes 3 seconds to finish and B 2 seconds. The request is sent via jQuery API.It means for stateful application, I will observe the following timeline in Chrome network tab: (1) the start time of both request are almost the same, since I send out two request in client code almost at the same time.(2) even though the second request itself takes 2 seconds to finish, the total processing time for it is 3 seconds waiting for A to finish first + 2 seconds = 5 seconds in the end. The above test did verify the conclusion.However when I change the approach to send request into ES6 fetch API, <%@page language="abap" %> <%@extension name="htmlb" prefix="htmlb" %> <!DOCTYPE html> <html> <head> <title>Jerry Test Stateful</title> </head> <body> <button onclick="fire()">Fire two request</button> <script> function wrapperOnFetch(url){ fetch(url).then(function(response){ return response.json(); }).then(function(json){ console.log(url + ":" + json.message); }); } function fire(){ wrapperOnFetch("first.json"); wrapperOnFetch("second.json"); } </script> </body> </html> the testing request for stateful application looks as below this time: The two requests are handled simultaneously ( request B only takes 2 seconds to finish, no 3 seconds’ wait time for A to finish this time ), the response of second request returns first before the first, which could be observed in console: why the latest ES6 API causes such discrepancy with known conclusion?Just compare the cookie of requests sent via these two kinds of API: Through comparison I get to know that the session cookiesap-contextid is not sent together with request triggered by ES6 Fetch API.Then in Fetch documentation I find out that I need to add option credentials: “include”. function wrapperOnFetch(url){ // enable session cookie sent with request fetch(url,{ credentials:"include" }).then(function(response){ return response.json(); }).then(function(json){ console.log(url + ":" + json.message); }); } After this change the stateful BSP application behaves as expected: the requests are handled in sequence. 本文来自云栖社区合作伙伴“汪子熙”,了解相关信息可以关注微信公众号"汪子熙"。

优秀的个人博客,低调大师

【CDN云课堂】技术专家直播分享:如何在CDN边缘节点执行你的JavaScript?

Serverless和边缘计算都是目前云计算领域备受瞩目的研究和应用方向。做为拥有超过130Tbps带宽分发能力的阿里云CDN,巨大的边缘网络有超过2800个节点遍布全球,如何将中心源站的计算能力下沉到边缘节点,进一步降低客户端访问延时进而提升用户体验,一直是阿里云CDN投入重点研究的方向。 阿里云CDN将Serverless和边缘计算的优势相融合,推出边缘轻量编程环境—EdgeRoutine,4月27日(周一)晚19:00,阿里云CDN技术专家将带来一场线上直播,分享阿里云CDN边缘轻量编程环境-EdgeRoutine的原理、使用场景和实践案例,欢迎大家点击报名观看。 直播介绍 直播主题:CDN边缘轻量编程环境—EdgeRoutine发布直播时间:4月27日(周一)晚19:00直播讲师:阿里云技术专家 洪晓龙直播内容:分享阿里云CDN

优秀的个人博客,低调大师

Javascript前端开发:阿里JS面试题让你深入了解原型与继承

题目如下: var F = function(){} Object.prototype.a = function(){ console.log('a()') } Function.prototype.b = function(){ console.log('b()') } var f = new F() F.a() F.b() f.a() f.b() 主要考查的技术点: 1.、原型与原型链 2、实例对象、构造函数、Object、 Function的关系 分析: F是个构造函数,而f是构造函数F的一个实例。 因为F instanceof Object == true、F instanceof Function == true 由此我们可以得出结论:F是Object 和 Function两个的实例,即F既能访问到a,也能访问到b。 所以F.a() 输出 a() F.b() 输出 b() 对于f,我们先来看下下面的结果: f并不是Function的实例,因为它本来就不是构造函数,所以就调用Function原型链上的相关属性和方法了,只能访问Object原型链。 所以f.a() 输出 a() 而f.b()就报错了。 接下来,我们具体分析下,它们是如何按路径查找的: f.a的查找路径: f自身: 没有 ---> f.__proto__(Object.prototype): 输出a() f.b的查找路径: f自身: 没有 ---> f.__proto__(Object.prototype): 没有 ---> f.__proto__.__proto__ (Object.prototype.__proto__): 因为找不到,所以报错 F.a的查找路径: F自身: 没有 ---> F.__proto__(Function.prototype): 没有 ---> F.__proto__.__proto__(Object.prototype): 输出 a() F.b的查找路径: F自身: 没有 ---> F.__proto__(Function.prototype): b()

优秀的个人博客,低调大师

GitHub重磅年度报告:JavaScript最热,中国开发者贡献稳居第二

GitHub大动作,开发者福利:重磅推出GitHub Actions! 在昨日举行的GitHub Universe 2018开发者大会上,GitHub发布了一款重量级产品:GitHub Actions,可直接运行部分代码的产品,彻底改变GitHub的使用方式。 正如平台主管Sam Lambert所说:“这将是GitHub史上最大的转变!” 除了发布GitHub Actions等新产品外,GitHub还公布了2018年年度报告。 GitHub Actions:开源、社区支持的平台 GitHub认为,作为一个开发者,大部分时间和经历应该只放在一件事情上,那就是代码。 在过去,开发者因配置工作流程,或使用不灵活的工具,浪费了大量的时间。而这正式GitHub要解决的问题。 现在,GitHub给开发者们提供了一种自动管理代码的工具,包括测试和技术支持。“

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册