js中的this

2017-01-05  本文已影响0人  Victor细节
// 默认绑定
// 在没有其他规则使用时的默认绑定
// function foo(){
//  console.log(this.a);
// }
// var a = 2;
// foo();

// 隐含绑定
// 调用点是否为一个环境对象,也叫作拥有者或者容器
// function foo(){
//  console.log( this.a );
// };
// var obj = {
//  a: 2,
//  b: 3,
//  fooo: foo,
// };
// obj.fooo();
// foo()被声明后作为引用属性添加到obj上,被obj拥有或者包含,所以this指代的是obj


// 隐含的丢失
// 隐含绑定丢失了他的绑定,这就意味着它要退回到默认绑定
// function foo() {
//  console.log(this.a);
// };
// var obj = {
//  a: 2,
//  fooo: foo,
// };
// var bar = obj.fooo;
// var a = 3;
// bar();

// 接下来我们考虑一下传递一个回调函数
// function foo(){
//  console.log(this.a);
// };
// function doFoo(fn){
//  fn();
// };
// var obj = {
//  a: 2,
//  fooo: foo,
// };
// var a = 3;

// doFoo(obj.fooo);

// 明确绑定
// 隐含绑定: 我们不得不改变目标对象使它自身包含一个对函数的引用,而后使用这个函数引用属性来间接的,将this绑定到这个对象上。
// 明确绑定: 我们强制一个函数调用使用某个特定的对象作为this绑定

// function foo(){
//  console.log(this.a);
// };
// var obj = {
//  a: 2,
// };
// foo.call( obj );

// 当然我们也可以传递原始的类型值(string boolean number),这个类型值会被包装在他的对象类型中,new String() new Number()...

// function sum(){
//  // console.log(this+2);  chai boxing
//  console.log(this); //boxing
// };
// sum.call(5);


// 硬绑定
// 有时候,单独依靠明确绑定仍然不能为我们先前提到的问题提供解决方案,也就是函数丢失原本的this绑定,或者被第三方框架覆盖,等问题。

// function foo(){
//  console.log(this.a);
// };
// var obj = {
//  a: 2,
// };
// var bar = function(){
//  foo.call( obj );
// };
// var a = 3;
// bar();
// bar.call(window);//不会被覆盖


// 用硬绑定将一个函数包装起来的最典型的方法,是为所有传入的参数和传出的返回值创建一个通道

// function foo(something){
//  console.log(this.a , something);
//  return this.a + something;
// };
// var obj = {
//  a: 2,
// };
// var bar = function(){
//  return foo.apply( obj,arguments );
// };
// var b = bar( 3 );
// console.log( b );

// 由于硬绑定是一个非常常用的模式,它已作为ES5中的內建工具提供:
// Function.prototype.bind

// 如下使用
// function foo(something){
//  console.log(this.a,something);
//  return this.a + something;
// };
// var obj = {
//  a: 2,
// };
// var bar = foo.bind(obj);
// var b = bar( 3 );
// console.log( b );

// new 绑定  
// js中构造器的定义:构造器仅仅是一个函数,它们偶然的被前置的new操作符调用,它们不依附于类,它们也不初始化类,它们本质上只是一般的函数,在被使用new来调用时改变了行为。

// 当在函数前面被加入new调用时,也就是构造器调用时,下面这些事情会自动完成
// 1.一个全新的对象会凭空创建 
// 2.这个新构建的对象会被接入原型链(prototype-linked)
// 3.这个新构建的对象被设置为函数调用的this绑定
// 4.除非函数返回一个它自己的其他对象,这个被new调用的函数将自动返回这个新构建的对象。


// 绑定的顺序
// 函数中的this绑定规则的优先级

// function foo() {
//     console.log( this.a );
// }

// var obj1 = {
//     a: 2,
//     foo: foo
// };

// var obj2 = {
//     a: 3,
//     foo: foo
// };

// obj1.foo(); // 2
// obj2.foo(); // 3

// obj1.foo.call( obj2 ); // 3
// obj2.foo.call( obj1 ); // 2

// =====得出结论===>明确绑定 的优先权要高于 隐含绑定

// function foo(something) {
//     this.a = something;
// }

// var obj1 = {
//     foo: foo
// };

// var obj2 = {};

// obj1.foo( 2 );
// console.log( obj1.a ); // 2

// obj1.foo.call( obj2, 3 );
// console.log( obj2.a ); // 3

// var bar = new obj1.foo( 4 );
// console.log( obj1.a ); // 2
// console.log( bar.a ); // 4

// =====得出结论===>new绑定 的优先级要高于 隐含绑定


// 总结this
// 现在,我们可以按照优先顺序来总结一下this的规则。

// 1.new 绑定
// 2.硬绑定
// 3.明确绑定
// 4.隐含绑定
// 5.默认绑定

// 以上,就是理解对于普通的函数调用来说的this绑定规则所需的全部。

// 当然还有一些特殊的特例

// 如果你传递null或undefined作为call,apply或bind的this绑定参数,那么这些值会被忽略掉,取而代之的是 默认绑定 规则将适用于这个调用。

// function foo() {

//     console.log( this.a );
//     console.log( this );
// }
// var a = 2;
// foo.call( null ); 


// 扩展
// 词法this   简单来说就是用一个变量保存this
// 我们刚刚涵盖了一般函数遵守的4种规则。但是ES6引入了一种不适用于这些规则特殊的函数:箭头函数(arrow-function)。

// 最后,复习一下
// 为执行中的函数判定this绑定需要找到这个函数的直接调用点。找到之后,4种规则将会以 这个 优先顺序施用于调用点:

/*
    1、被new调用?使用新构建的对象。
    2、被call或apply(或 bind)调用?使用指定的对象。
    3、被持有调用的环境对象调用?使用那个环境对象。
    4、默认:strict mode下是undefined,否则就是全局对象。
*/
上一篇 下一篇

猜你喜欢

热点阅读