您的位置:首页 > Web前端 > JavaScript

JS——prototype、闭包、跨域

2017-02-25 22:43 204 查看

prototype

Js所有的函数都有一个prototype属性,这个属性引用了一个对象,即原型对象,也简称原型。

javascript中的每个对象都有prototype属性,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用。

//原型继承
A.prototype = new B();


理解prototype不应把它和继承混淆。A的prototype为B的一个实例,可以理解A将B中的方法和属性全部克隆了一遍。A能使用B的方法和属性。这里强调的是克隆而不是继承。可以出现这种情况:A的prototype是B的实例,同时B的prototype也是A的实例。

//实例1
function baseClass()
{
this.showMsg = function()
{
alert("baseClass::showMsg");
}
}

function extendClass()
{
}

extendClass.prototype = new baseClass();
var instance = new extendClass();
instance.showMsg(); // 显示baseClass::showMsg

//实例2
function baseClass()
{
this.showMsg = function()
{
alert("baseClass::showMsg");
}
}

function extendClass()
{
this.showMsg =function ()
{
alert("extendClass::showMsg");
}
}

extendClass.prototype = new baseClass();
var instance = new extendClass();

instance.showMsg();//显示extendClass::showMsg

//实例3,在2的基础上,如果想调用父类
extendClass.prototype = new baseClass();
var instance = new extendClass();

var baseinstance = new baseClass();
baseinstance.showMsg.call(instance);//显示baseClass::showMsg


prototype 属性使您有能力向对象添加属性和方法。

object.prototype.name=value


例如添加属性:

function employee(name,job,born)
{
this.name=name;
this.job=job;
this.born=born;
}

var bill=new employee("Bill Gates","Engineer",
4000
1985);

employee.prototype.salary=null;
bill.salary=20000;


一旦定义了原型属性或原型方法,则所有通过该构造函数实例化出来的所有对象,都继承了这些原型属性和原型方法,这是通过内部的proto链来实现的。

原型对象初始是空的(并不是类中预先有多少属性和方法它就有多少)

闭包

要理解闭包,首先必须理解Javascript特殊的变量作用域。

变量的作用域无非就是两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。另一方面,在函数外部自然无法读取函数内的局部变量。

这就是Javascript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。并把这个函数作为返回值,不就可以在第一个函数外部读取它的内部变量了吗!

function f1(){
    var n=999;
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999


f2函数,就是闭包。是将函数内部和函数外部连接起来的一座桥梁。

闭包就是嵌套在函数里面的内部函数,并且该内部函数可以访问外部函数中声明的所有局部变量、参数和其他内部函数。当该内部函数在外部函数外被调用,就生成了闭包。(实际上任何函数都是全局作用域的内部函数,都能访问全局变量,所以都是window的闭包)

第一大用途,就是读取函数内部的变量

第二大用途,就是让变量的值始终保存在内存中。

在动态执行环境中,数据实时地发生变化,为了保持这些非持久型变量的值,我们用闭包这种载体来存储这些动态数据。这就是闭包的作用。也就说遇到需要存储动态变化的数据或将被回收的数据时,我们可以通过外面再包裹一层函数形成闭包来解决。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

跨域

js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。

严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。

a.baidu.com访问b.baidu.com 是跨域;

a.baidu.com:8080访问a.baidu.com:80 是跨域;

http://a.baidu.com访问https://a.baidu.com 是跨域

jsonp

在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

ajax(header(‘Access-Control-AllowOrgin:http://….’))

document.domain+iframe

只适用于不同子域的框架间的交互

比如,有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html

只要把http://www.example.com/a.htmlhttp://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了

window.name+iframe

在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

所以把想要获取的数据在window.name中进行设置即可。

想要即使a.html页面不跳转也能得到data.html里的数据。答案就是在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。同样的,必须把这个iframe的src设成跟a.html页面同一个域才行

window.location.hash+iframe

在url: http://a.com#helloword中的‘#helloworld’就是location.hash,改变hash并不会导致页面刷新,所以可以利用hash值来进行数据传递。

假设域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息,cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面,这时的hash值可以做参数传递用。

html5 postMessage+iframe

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息。

该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。

调用postMessage方法的window对象是指要接收消息的那一个window对象

需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

以上为解决方法,jsonp最常见
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: