一、javascript的闭包javascript
闭包简单的说就说一个函数能访问外部函数的变量,这就是闭包前端
function a(x){ var item = 3; function b(y){ console.log(x+y+item); } }
a函数中的b函数就是闭包了,b函数可使用a函数的局部变量,参数,最典型的的闭包应该就是下面这样,将定义在函数中的函数做为返回值java
function a(x){ var item = 3; function b(y){ console.log(x+y+item); } return b; }
闭包的缺点是,由于内部闭包函数能够访问外部函数的变量,因此外部函数的变量不能被释放,若是闭包嵌套过多,会致使内存占用大,要合理使用闭包。web
二、new操做符到底作了什么ajax
首先,new操做符为咱们建立了一个新的空对象,而后this变量指向该对象。json
其次,空对象的原型指向构造函数的原型,小程序
最后,改变构造函数内部的this的指向后端
三、改变函数内部this指针的指向函数数组
call和apply,假设要改变fn函数内部的this指向,指向obj,那么能够fn.call(boj);或者fn.apply(boj);那么问题来了,call和apply和区别是什么,其实call和apply的区别在于参数,他们两个的第一个参数都是同样的,表示调用该函数的对象,apply的第二个参数是数组,是[arg1,arg2,arg3]这种形式,而call是 arg1,arg2,arg3这样的形式。还有一个bind函数。浏览器
var bar = fn.bind(obj);那么fn中的this就指向obj对象了,bind函数返回新的函数,这个函数内的this指针指向obj对象。
四、javascript的做用域和做用域链
javascript的做用域指的是变量的做用范围,内部做用域由函数的形参,实参,局部变量,函数构成,内部做用域和外部的做用域一层层的连接起来造成做用域链,当在函数内部要访问一个变量的时候,首先查找本身内部做用域有没有这个变量,若是没有就到外部的做用域去查找,仍是没有的话,就到再外面一层做用域中找,直至window所在的做用域,每一个函数在声明的时候就默认有一个外部做用域链存在了,好比:
var t=4; function foo(){ var tem=12; function bar(){ var temo=34; console.log(t+" "+tem+" "+temo); } }
在bar函数中找t变量的过程就是,先到本身的内部做用域中找,发现没有找到,而后到bar所在的最近的外部环境中找,也就是foo的内部做用域,仍是没有找到,再到window的做用域中找,结果找到了。
五、javascript的继承
原型继承
function A(name){ this.name = name; } A.prototype.sayName = function(){ console.log(this.name); } function B(age){ this.age = age; } B.prototype = new A("lhz"); var foo = new B(18); foo.age; //18 foo.name; //lhz foo.sayName(); //lhz
这种方法的缺点:第一个缺点是全部子类共享父类实例,若是某一个子类修改了父类,其余的子类在继承的时候,会形成意想不到的后果。第二个缺点是在构造子类实例的时候,不能给父类传递参数。
构造函数继承:
function B(age,name){ this.age = age; A.call(this, name); } var foo = new B(18, "lhz"); foo.name; //lhz foo.age; //18 foo.sayName(); //undefined
采用这种方式继承是把A中的属性加到this上面,这样name至关于就是B的属性,sayName不在A的构造函数中,因此访问不到sayName。这种方法的缺点是父类的prototype中的函数不能复用。
原型继承+构造函数继承
function B(age, name){ this.age = age; A.all(this,name); } B.prototype = new A("mbj"); var foo = new B(18, "lhz"); foo.name; //lhz foo.age; //18 foo.sayName(); //lhz
这样就能够成功访问sayName函数了,结合了上述两种方式的优势,可是这种方式也有缺点,那就是占用的空间更大了。
六、ajax的优缺点
优势:
(1)无刷新更新数据
AJAX最大优势就是能在不刷新整个页面的前提下与服务器通讯维护数据。这使得Web应用程序更为迅捷地响应用户交互,并避免了在网络上发送那些没有改变的信息,减小用户等待时间,带来很是好的用户体验。
(2)异步与服务器通讯
AJAX使用异步方式与服务器通讯,不须要打断用户的操做,具备更加迅速的响应能力。优化了Browser和Server之间的沟通,减小没必要要的数据传输、时间及下降网络上数据流量。
(3)前端和后端负载平衡
AJAX能够把之前一些服务器负担的工做转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。而且减轻服务器的负担,AJAX的原则是“按需取数据”,能够最大程度的减小冗余请求和响应对服务器形成的负担,提高站点性能。
(4)基于标准被普遍支持
AJAX基于标准化的并被普遍支持的技术,不须要下载浏览器插件或者小程序,但须要客户容许JavaScript在浏览器上执行。随着Ajax的成熟,一些简化Ajax使用方法的程序库也相继问世。一样,也出现了另外一种辅助程序设计的技术,为那些不支持JavaScript的用户提供替代功能。
(5)界面与应用分离
Ajax使WEB中的界面与应用分离(也能够说是数据与呈现分离),有利于分工合做、减小非技术人员对页面的修改形成的WEB应用程序错误、提升效率、也更加适用于如今的发布系统。
缺点:
(1)ajax干掉了back和history功能,即对浏览器机制的破坏
在动态更新页面的状况下,用户没法回到前一个页面状态,由于浏览器仅能记忆历史记录中的静态页面。一个被完整读入的页面与一个已经被动态修改过的页面之间的差异很是微妙;用户一般会但愿单击后退按钮可以取消他们的前一次操做,可是在Ajax应用程序中,这将没法实现。
后退按钮是一个标准的web站点的重要功能,可是它无法和js进行很好的合做。这是Ajax所带来的一个比较严重的问题,由于用户每每是但愿可以经过后退来取消前一次操做的。那么对于这个问题有没有办法?答案是确定的,用过Gmail的知道,Gmail下面采用的Ajax技术解决了这个问题,在Gmail下面是能够后退的,可是,它也并不能改变Ajax的机制,它只是采用的一个比较笨可是有效的办法,即用户单击后退按钮访问历史记录时,经过建立或使用一个隐藏的IFRAME来重现页面上的变动。(例如,当用户在Google Maps中单击后退时,它在一个隐藏的IFRAME中进行搜索,而后将搜索结果反映到Ajax元素上,以便将应用程序状态恢复到当时的状态。)
可是,虽说这个问题是能够解决的,可是它所带来的开发成本是很是高的,并与Ajax框架所要求的快速开发是相背离的。这是Ajax所带来的一个很是严重的问题。
一个相关的观点认为,使用动态页面更新使得用户难于将某个特定的状态保存到收藏夹中。该问题的解决方案也已出现,大部分都使用URL片段标识符(一般被称为锚点,即URL中#后面的部分)来保持跟踪,容许用户回到指定的某个应用程序状态。(许多浏览器容许JavaScript动态更新锚点,这使得Ajax应用程序可以在更新显示内容的同时更新锚点。)这些解决方案也同时解决了许多关于不支持后退按钮的争论。
(2)ajax的安全问题
AJAX技术给用户带来很好的用户体验的同时也对IT企业带来了新的安全威胁,Ajax技术就如同对企业数据创建了一个直接通道。这使得开发者在不经意间会暴露比之前更多的数据和服务器逻辑。Ajax的逻辑能够对客户端的安全扫描技术隐藏起来,容许黑客从远端服务器上创建新的攻击。还有Ajax也难以免一些已知的安全弱点,诸如跨站点脚步攻击、SQL注入攻击和基于Credentials的安全漏洞等等。
(3)对搜索引擎支持比较弱
对搜索引擎的支持比较弱。若是使用不当,AJAX会增大网络数据的流量,从而下降整个系统的性能。
(4)破坏程序的异常处理机制
至少从目前看来,像Ajax.dll,Ajaxpro.dll这些Ajax框架是会破坏程序的异常机制的。关于这个问题,曾在开发过程当中遇到过,可是查了一下网上几乎没有相关的介绍。后来作了一次试验,分别采用Ajax和传统的form提交的模式来删除一条数据……给咱们的调试带来了很大的困难。
(5)违背url和资源定位的初衷
例如,我给你一个URL地址,若是采用了Ajax技术,也许你在该URL地址下面看到的和我在这个URL地址下看到的内容是不一样的。这个和资源定位的初衷是相背离的。
七、用代码实现一个简易的 jsonp demo
export function jsonp (url , data, callback){
url += (url.indexOf("?") < 0 ? "?" : "&") + param(data);
return new Promise((resolve, reject) =>{
const script = document.createElement('script');
const callBackSymbol = `cb${Math floor( Math.random() * 1000 )}`;
if(callback){
url += `&${callback}=${callbackSymbol}`;
}else{
url += `&callback=${callbackSymbol}`;
}
window[callbackSymbol] = function(res){
document.querySelector("head").removeChild(script);
delete window.callbackSymbol;
resolve(res);
}
script.setAttribute("src", url);
document.querySelector("head").appendChild(script);
})
}