什么是作用域?
作用域分为局部作用域和全局作用域 作用域往往和变量有关系
在局部作用域里面可以访问全局作用域的变量
局部作用域外面就访问不到局部作用域里面所声明的变量
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)
function localFunction()
{
var innerLocalVariable='This is inner local Variable'
console.log(innerLocalVariable)
}
localFunction()
}
globalFunction()
什么是 上下文?
上下文常常代表this变量的值,以及他的指向,他决定一个函数怎么被调用
当一个函数作为一个方法被调用的时候 this 总是指向调用这个方法的对象
// var pet= {
// words: '...',
// speak: function() {
// console.log(this.words) //this 在这里面暂时可以理解为指向上一个
//pet进去,speak进去 所以指向的是pet
// console.log(this === pet)//return true
// }
// }
// pet.speak()
// function pet(words){
// this.words=words
// console.log(this.words) //只有一个pet 指向的上一个就是global全局
// console.log(this==global)//return true
// }
// pet('...')
function Pet(words) {
this.words=words
this.speak=function(){
console.log(this.words)
console.log(this)
}
}
var cat =new Pet('miao')
cat.speak()
2.call和apply
使用call和apply可以改变上下文执行对象,可以在自定义上下文中执行函数,两者作用相同,仅仅是方法的第二个参数不同,call直接使用参数列表,apply使用参数数组。具体作用是调用一个对象的方法,以另一个对象替换当前对象,实际上市改变this指向的对象内容。看代码:
var pet= {
words: '...',
speak: function(say){
console.log(say + ' ' + this.words)
}
}
//pet.speak('Speak')
//return Speak ....
var pet= {
words: '...',
speak: function(say){
console.log(say + ' ' + this.words)
}
}
var dog={
words: 'Wang'
}
pet.speak.call(dog,'Speak')
dog对象本来没有speak方法,通过call的方法,偷梁换柱地将原本指向pet的this变量指向了dog,因此在运行时,this.words='wang',所以打印出Speak wang。通过这种方式,我们可以使一个对象去使用另一个对象的方法,一个容易想到的应用场景就是继承。
function Pet(words){
this.words=words
this.speak=function(){
console.log(this.words);
}
}
function Dog(words)
{
//Pet.call(this,words);//pet的this 指向当前的dog,
//使dog拥有pet的方法
Pet.apply(this,[words]);//apply中的第二个参数是一个数组
}
var dog=new Dog('wang wang ');
dog.speak();
我们可以看到,使用call和apply实现的效果是一样的,仅仅是参数的差异,一个直接使用words,一个要使用数组形式的[words]。再看一个例子:
function print(a, b, c, d){
//alert(a + b + c + d);
console.log(a+b+c+d)
}
function example(a, b , c , d){
//用call方式借用print,参数显式打散传递
print.call(this, a, b, c, d);
//用apply方式借用print, 参数作为一个数组传递,
//可以直接用JavaScript方法内本身有的arguments数组
print.apply(this, arguments);
//或者封装成数组
print.apply(this, [a, b, c, d]);
}
//下面将显示'鸡年大吉'
example('鸡', '年', '大', '吉');
至于什么时候使用call,什么时候使用apply,一般当参数比较明确的时候,两者都可以,当参数不明确时,推荐使用apply+arguments的方式。