1.this
this到底绑定或者引用的是哪个对象环境决定于函数被调用的地方。而函数的调用有不同的方式,在不同的方式中调用决定this引用的是哪个对象是由四种规则确定的。
1.1默认绑定全局变量
函数被单独定义和调用的时候,应用的规则就是绑定全局变量.
function fn() {
console.log( this.a );
}
var a = 2;
fn(); // 2 -- fn单独调用,this引用window
1.2隐式绑定
隐式调用的意思是,函数调用时拥有一个上下文对象,就好像这个函数是属于该对象的一样(字面量表示法)
function fn(){
console.log( this.a );
}
var obj = {
a: 2,
fn: fn
};
obj.fn(); // 2 -- this引用obj。
失去隐式绑定的情况,依然是默认绑定全局变量
function fn() {
console.log( this.a );
}
var obj = {
a: 2,
fn: fn
};
var bar = obj.fn; // 函数引用传递
var a = "全局"; // 定义全局变量
bar(); // "全局"
1.3显式绑定
利用call()、apply();接收的第一个参数即是上下文对象并将其赋给this。
function fn() {
console.log( this.a );
}
var obj = {
a: 2
};
fn.call( obj ); // 2
如果传递为null,那么结果就是在绑定默认全局变量
function fn() {
console.log( this.a );
}
var obj = {
a: 2
};
var a = 10;
fn.call( null); // 10
1.4 new新对象绑定
如果是一个构造函数,那么用new来调用,那么绑定的将是新创建的对象。
function fn(a) {
this.a = a;
}
var bar = new fn( 2 );
console.log( bar.a );// 2
小结: 如果在javascript语言里没有通过new(包括对象字面量定义)、call和apply改变函数的this指针,函数的this指针都是指向window的。
2.new操作符
通过new操作符实例化对象,执行如下代码:
var obj = new Base();
new操作符具体干了什么呢?其实很简单,就干了三件事情。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
第一行,我们创建了一个空对象obj
第二行,我们将这个空对象的proto成员指向了Base函数对象prototype成员对象
第三行,我们将Base函数对象的this指针替换成obj,然后再调用Base函数
3.call and apply
call() 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法.
注意:该方法的作用和 apply() 方法类似,只有一个区别,就是call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组。
语法:fun.call(thisArg[, arg1[, arg2[, ...]]])
thisArg即为fun方法指定的this对象。
实例
1.借用构造函数继承
function Product(name, price) {
this.name = name;
this.price = price;
if (price < 0) {
throw RangeError('Cannot create product ' +
this.name + ' with a negative price');
}
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
var cheese = new Food('feta', 5);
2使用call方法调用函数并且指定上下文的’this’
function greet() {
var reply = [this.person, 'Is An Awesome', this.role].join(' ');
console.log(reply);
}
var i = {
person: 'Douglas Crockford', role: 'Javascript Developer'
};
greet.call(i);