this
函数上下文中的this
<script>
// 如果要把this的值从一个环境传到另一个,就要用call或apply。
// 对象可以作为bind或apply的第一个参数传递,并且该参数将绑定到this
var obj = {a: 'Custom'};
// 声明一个变量,并将该变量作为全局对象window的属性
var a = 'Global';
function whatThis() {
return this.a; // this的值取决于函数被调用的方式
}
// 'Global' 因为这个函数中this没有被设定,所以它默认是全局window对象。
whatThis();
// ’Custom' 因为函数中this被设置为obj
whatThis.call(obj);
// ’Custom' 因为函数中this被设置为obj
whatThis.apply(obj);
</script>
this和对象转换
<script>
function add(c, d) {
return this.a + this.b + c + d;
}
var o = {a: 1, b: 3};
// 第一个参数是用作"this"的对象,其余参数用作函数的参数(其中一个参数是数组,则数组成员用作函数参数)
add.call(o, 6, 8); // 18
add.apply(o, [10, 20]); // 34
</script>
<script>
/*
在非严格模式下使用call和apply时,如果用作this的值不是对象,则会被尝试转换为对象。
null和undefined被转换为全局对象。原始值如”7“或”foo“会使用相应构造函数转换为对象。
因此”7“会被转换为new Number(7)生成的对象,字符串“foo”会转换为new String('foo')生成的对象。
*/
function bar() {
console.log(Object.prototype.toString.call(this));
}
bar.call(7); //[Object Number]
bar.call('foo'); // [Object String]
bar.call(undefined); // [Object Window]
</script>
bind方法
<script>
/*
Function.prototype.bind():调用f.bind(someObject)会创建一个与f具有相同函数体
和作用域的函数,但是在这个新函数中,this将永久地绑定到bind的第一个参数,无论这个函数
函数时如何被调用的。
*/
function f() {
return this.a;
}
var g = f.bind( {a: "azerty"} );
console.log(g()); // azerty 按照bind上述bind注释,g函数将和f一样拥有相同函数体和作用域,那this也将永远指向对象:{a: "azerty"}
var h = g.bind( {b: "yoo"} );
console.log(h()); // azerty 重新绑定新对象没用,只指向{a: "azerty"}
var o = {
a: 37,
f: f,
g: g,
h: h
};
debugger;
console.log(o.a); // 37
console.log(o.f()); // 37
console.log(o.g()); // azerty
console.log(o.h()); // azerty
</script>
箭头函数
<script>
/*
箭头函数中,this与封闭词法环境的this保持一致,在全局代码中,它将被设置为全局对象:
*/
debugger;
var globalObject = this;
var foo = (() => this); // function foo() {return this}
console.log(foo() === globalObject);
// 作为对象一个方法调用
var obj = {foo: foo};
console.log(obj.foo() === globalObject); //true
// 尝试使用call来设定this
console.log(foo.call(obj) === globalObject); // true
// 尝试使用bind来设定this
foo == foo.bind(obj);
console.log(foo() === globalObject ); // true
</script>
<script>
/*
创建一个含有bar方法的obj对象,
bar返回一个函数,
这个函数返回this,
这个返回的函数是以箭头函数创建的,
所以它的this被永久绑定到了它外层函数的this。
bar的值可以在调用中设置,这反过来又设置了返回函数的值
*/
var obj = {
bar: function() {
var x = (() => this);
return x;
}
};
debugger;
/*
作为obj对象的一个方法来调用bar,把它的this绑定到obj。
将返回的函数的引用赋值给fn
*/
var fn = obj.bar();
/*
* 直接调用fn而不设置this,
* 通常(即不使用箭头函数的情况)默认为全局对象
* 若在严格模式则为undefined
*/
console.log(fn() === obj); // true
/*
* 但是注意,如果你只是引用obj的方法,
* 而没有调用它
*/
var fn2 = obj.bar;
/*那么调用箭头函数后,this指向window,因为它从bar继承this*/
console.log(fn2()() == window); // true
</script>
作为构造函数
<script>
/*
当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。
虽然构造函数返回默认值是this所指的那个对象,但它仍可以手动设置返回其他对象
(如果返回值不是一个对象,则返回this对象)
*/
/*
构造函数这样工作:
functin MyCostructor(para) {
// 函数实体写在这里
// 根据需要在this上创建属性,然后赋值给它们,比如:
this.fum = "nom";
// 等等……
// 看到这里,对以前看过的内容有了新的理解,this.fum是在为对象增加属性值,
// 而哪个对象使用这个函数作为构造函数,则this指向哪个对象,fum也作为哪个对象的属性值。
this.ele = para; // this.para = para
// 字符串被赋值是要加上双引号的,若字符没有双引号作为值,那它就是变量。
// 故this.para = para可以看做this.para是对象有个名为para的属性(属性值不可变),
// 等号右侧的para是变量值,它可以是任何类型值,具体是要看构造时传入的是什么类型(字符串就是双引号)
// 啊……知识的海洋里又看到一点希望~~~
// 如果函数具有返回对象的return语句,则该对象将是new表达式的结果。
// 否则,表达式的结果是当前绑定到this的对象(即通常常见的情况~)
// 即this 将是指向被return的对象,而不是用构造函数创建的对象。
}
*/
// 通常常见的情况
function C() {
this.a = 36;
}
var o = new C();
console.log(o.a); // 36
// 构造函数返回值为对象
function C2() {
this.a = 36;
this.b = 545;
return { a: 32, c: 666 };
}
o = new C2();
console.log(o.a); // 32
console.log(o.b); // undefined
console.log(o.c); // 666
</script>
this范围
<script>
var name = '希望';
var age = 17;
var obj = {
name: '校长',
objAge: this.age, // 这里的this指向window
myFun: function() {
// 这里的this指向obj
console.log(this.name + " 年龄 " + this.age);
}
}
debugger;
obj.objAge; // 17
obj.myFun(); // 校长 年龄 undefined
</script>