一、什么是作用域、什么是上下文
作用域和调用函数,访问变量的能力有关,上下文和this关键字有关是调用当前可执行代码的引用。
1,作用域
分为局部作用域,全局作用域,处于局部作用域里面可以访问到全局作用域变量,在局部作用域外面,访问不到局部作用域里面的变量。
例一:
var globalVariable = 'This is global variable'; //全局变量function globalFunction(){ //全局函数,里面就是局部作用域 var localVariable = "This is local variable"; console.log('visit global/local variable'); console.log(globalVariable); console.log(localVariable);}globalFunction();
例二:
var globalVariable = 'This is global variable'; //全局变量function globalFunction(){ //全局函数,里面就是局部作用域 var localVariable = "This is local variable"; console.log('visit global/local variable'); console.log(globalVariable); console.log(localVariable); //修改全局变量 globalVariable = 'This is changed variable'; console.log(globalVariable); //局部函数,只能在globalFunction()内部调用 function localFunction(){ //在这个作用域里能访问到全局作用域 和 globalFunction() var innerLocalVariable = 'This is inner ocal variable'; console.log('visit global/local/innerLocak variable'); console.log(globalVariable); console.log(localVariable); console.log(innerLocalVariable); } localFunction();//调用内部函数}globalFunction();
2、上下文
上下文常代表this变量的值,以及他的指向,他决定一个函数怎么被调用,当一个函数,可以作为一个对象的方法被调用时,This指向调用这个方法的对象。
例一:
//上下文环境var pet ={ words: "...", speak: function(){ console.log(this.words); console.log(this === pet);//返回true }}pet.speak();//pet调用speak 这时speak里面的this指向pet
另一种情况
//另一种情况function pet(words){ this.words = words; console.log(this.words); console.log(this);}pet('...')
这个this指向执行环境最顶层变量,global, 此时调用函数的对象时global
console.log( this ===global) true
情况3:
function Pet(words){ this.words = words; this.speak = function(){ console.log(this.words); console.log(this); //cat }}var cat = new Pet('Miao');cat.speak()
通常把拥有者称为执行上下文,this是javaScript语言的一个关键字,代表函数运行时的自动生成的一个函数对象,只能在函数内部使用,this指向函数拥有者,在全局运行的上下文中this指向全局对象。在函数内部this取决于函被调用的方式:
- 作为对象的方法,使用Pet对象时,调用speak方法,择this指向的上下文执行对象就是Pet对象。
- 函数的调用,此时内部的this默认指向全局对象,在浏览器中指的是window,nodeJs中指的是global.
- 构造函数中使用this,this指向新构建好的实例对象。
二、call() apply() 可以改变上下文执行对象
call, apply都属于Function.的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性
相同点:两个方法产生的作用是完全一样的,以某个方法当做被指定对象的方法来执行。
不同点:方法传递的参数不同
foo.call(thisObj, arg1,arg2,arg3) == foo.apply(thisObj, arguments)==this.foo(arg1, arg2, arg3)
foo是一个方法,thisObj是方法执行时上下文相关对象,arg1, arg2, arg3是传给foo方法的参数.这里所谓的方法执行时上下文相关对象,就是在类实例化后对象中的this.
在JavaScript中,代码总是有一个上下文对象,代码处理该对象之内. 上下文对象是通过this变量来体现的, 这个this变量永远指向当前代码所处的对象中.
1.call 方法
可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
nodeJS事例1:
var pet = { words :"....", speak: function(say){ console.log(say + ' ' + this.words); }}//pet.speak('Speak'); //this指向petvar dog = { words ='wang'}pet.speak.call(dog,'Speak');
调用的方法是 pet.speak, 理论上this指针指向 pet,但通过call(),改变了执行上下文,将this指向了dog, 'speak'为传入的参数,指定dog对象为上下文
nodeJS事例2 --继承:
//继承function Pet(words){ this.words = words; this.speak = function(){ console.log(this.words); }}function Dog(words){ Pet.call(this,words); //构造函数,此时this指向新创关键的实例对象 // 将Pet里面的this指向当前Dog //Pet.apply(this , arguments);//传入数组 console.log(this); //Dog { words: 'Wang', speak: [Function] }}var dog = new Dog('Wang');dog.speak();
js事例
例1:
function add(a,b) { alert(a+b); } function sub(a,b) { alert(a-b); } add.call(sub,3,1);
这个例子中的意思就是用 add 来替换 sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4);
例2:
function Class1() { this.name = "class1"; this.showNam = function() { alert(this.name); } } function Class2() { this.name = "class2"; } var c1 = new Class1(); var c2 = new Class2(); c1.showNam.call(c2);
注意,call 的意思是把 c1 的方法放到c2上执行,原来c2是没有showNam() 方法,现在是把c1 的showNam()方法放到 c2 上来执行,所以this.name 应该是 class2,执行的结果就是:alert("class2");
参考文献: