你不知道的JavaScript:this和对象原型

koeb4636 7年前
   <p>this在调用时绑定,完全取决于函数的调用位置。</p>    <p><strong>绑定规则</strong></p>    <ol>     <li>默认绑定(独立函数调用,绑定到全局对象,但严格模式下this会绑定到undefined) <pre>  <code class="language-javascript">function foo() {   console.log(this.a);  }  var a = 2;  foo(); // 2</code></pre> </li>     <li>隐式绑定:当函数引用有上下文对象时,this绑定在这个上下文对象上,最后一层调用位置起作用 <pre>  <code class="language-javascript">function foo() {   console.log(this.a);  }  var obj = {   a: 2,   foo: foo  }  var a = "hello";  obj.foo(); // 2</code></pre> 隐式丢失 <pre>  <code class="language-javascript">function foo() {   console.log(this.a);  }  var obj = {   a: 2,   foo: foo  }  var bar = obj.foo; //实际上指向foo本身,独立函数调用  var a = "hello world";  bar(); // hello world</code></pre> </li>     <li>显示绑定,call和apply,第一个参数是对象,函数调用时将this绑定到这个对象上<br> 硬绑定 <pre>  <code class="language-javascript">function foo() {   console.log(this.a);  }  var obj = {   a: 2  }  var bar = function() {   foo.call(obj);  }  bar(); // 2  setTimeout(bar, 1000); // 2  var a = "hello world";  bar.call(window); // 2</code></pre> </li>     <li>new绑定:用new调用函数时,会创建一个新对象,并将这个新对象绑定到函数调用的this上。 <pre>  <code class="language-javascript">function foo(a) {   this.a = a;  }  var bar = new foo(2); //将返回的对象bar绑定在foo的this上  console.log(bar.a); //2</code></pre> </li>    </ol>    <p><strong>绑定规则优先级</strong></p>    <ol>     <li>显示绑定高于隐式绑定 <pre>  <code class="language-javascript">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,先将foo中的this绑定到obj2,在被obj1调用  obj2.foo.call(obj1);//2</code></pre> </li>     <li>new绑定高于隐式绑定 <pre>  <code class="language-javascript">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(bar.a);//4  console.log(obj1.a);//2</code></pre> </li>     <li>new绑定高于硬绑定(new 和call或者apply不能同时使用) <pre>  <code class="language-javascript">function foo(something) {   this.a = something;  }  var obj1 = {};  var bar = foo.bind(obj1);  bar(2);  console.log(obj1.a); //2  var baz = new bar(3);  console.log(obj1.a); //2  console.log(baz.a);//3</code></pre> new中使用硬绑定,可以预先设置一些参数,使用new初始化时只需传入其他的参数,柯里化的一种 <pre>  <code class="language-javascript">function foo(p1, p2) {   this.val = p1 + p2;  }  var bar = foo.bind(null, "p1"); //不关心硬绑定到哪里,this会被new修改  var baz = new bar("p2");  console.log(baz.val);//p1p2</code></pre> </li>    </ol>    <p><strong>绑定例外</strong></p>    <p>把null或者undefined传入call,apply,bind等,忽略this</p>    <pre>  <code class="language-javascript">function foo() {      console.log(this.a);  }  var a = 2;  foo.call(null);//2,实际使用默认绑定</code></pre>    <p>间接引用</p>    <pre>  <code class="language-javascript">function foo() {      console.log(this.a);  }  var a = 2;  var o = {a:3, foo:foo};  var p = {a:4};  o.foo();//3  (p.foo = o.foo)();//2,返回值是目标函数的引用,所以是默认绑定</code></pre>    <p>软绑定</p>    <pre>  <code class="language-javascript">function foo() {      console.log("name: " + this.name);  }  var obj = {name:obj},      obj2 = {name:obj2},      obj3 = {name:obj2};  var fooOBJ = foo.softBind(obj);  fooOBJ(); //name:obj  obj2.foo = foo.softBind(obj);  obj2.foo();//name:obj2  fooOBJ.call(obj3);//name:obj3  setTimeout(obj2.foo, 10);//name:obj</code></pre>    <p><strong>箭头函数</strong>:根据外层作用域来决定this,箭头函数的绑定无法修改</p>    <pre>  <code class="language-javascript">function foo() {      return (a) => {          //this继承自foo()          console.log(this.a);      }  }  var obj1 = {a:2};  var obj2 = {a:3};  var bar = foo.call(obj1);  bar.call(obj2);//2</code></pre>    <p><strong>数组</strong>,添加数字类属性,数组长度增加</p>    <pre>  <code class="language-javascript">var myArray = ["foo", 42, "bar"];  myArray.baz = "baz";  console.log(myArray.length);  myArray["3"] = "baz";  console.log(myArray.length);</code></pre>    <p><strong>属性描述符</strong>:writable,是否可以修改属性的值;configurable,属性描述符是否可修改,为false的话禁止删除这个属性;Enumerable,可枚举</p>    <p><strong>getter / setter</strong></p>    <pre>  <code class="language-javascript">var myObject = {      get a() {          return this._a_;      },      set a(val) {          this._a_ = val * 2;       }  };  myObject.a = 2;  console.log(myObject.a);</code></pre>    <p>属性的存在性,值为undefined或者不存在都返回</p>    <pre>  <code class="language-javascript">undefined  var myObject = {      a:2  };  "a" in myObject; // true, 会检查原型链  "b" in myObject; //false  myObject.hasOwnProperty("a");//true,只检查对象本身  myObject.hasOwnProperty("b");//false</code></pre>    <p><strong>混入</strong></p>    <p>1、 显示混入</p>    <pre>  <code class="language-javascript">function mixin(sourceObj, targetObj) {      for(var key in sourceObj) {          if(!(key in targetObj)) {              targetObj[key] = sourceObj[key];          }      }      return targetObj;  }    var Vehicle = {      engine: 1,      ignition: function() {          console.log("turning on my engine.");      },      drive: function() {          this.ignition();          console.log("steering and moving forward!");      }  };    var Car = mixin(Vehicle, {      wheels: 4,      drive: function() {          Vehicle.drive.call(this);          console.log("rolling on all" + this.wheels + "wheels!");      }  });</code></pre>    <p>2、混合混入,先进行复制,之后再特殊化,效率低,不常用</p>    <pre>  <code class="language-javascript">function mixin(sourceObj, targetObj) {      for(var key in sourceObj) {          targetObj[key] = sourceObj[key];      }      return targetObj;  }    var Vehicle = {       //...  };    var Car = mixin(Vehicle, {});  mixin({      wheels: 4,      drive:function(){          //...      }  }, car);</code></pre>    <p>3、寄生继承</p>    <pre>  <code class="language-javascript">function Vehicle() {      this.engine = 1;  }  Vehicle.prototype.ignition = function() {      console.log("turning on my engine.");  };  Vehicle.prototype.drive = function() {      this.ignition();      console.log("steering and move forward!");  };  function Car() {      var car = new Vehicle();      car.wheels = 4;      var vehDrive = car.drive;      car.drive = function() {          vehDrive.call(this);          console.log("rolling on all" + this.wheels + "wheels!");      }      return car;  }  var mycar = new Car();  mycar.drive();</code></pre>    <p>4、 隐式混入</p>    <pre>  <code class="language-javascript">var Something = {      cool: function() {          this.greetng = "hello world";          this.count = this.count ? this.count + 1 : 1;      }  };    Something.cool();  Something.greetng; // hello world  Something.count; // 1    var Another = {      cool: function() {          Something.cool.call(this);      }  };  Another.cool();  Another.greetng; //hello world  Another.count; // 1, count 不是共享状态</code></pre>    <p>隐式屏蔽</p>    <pre>  <code class="language-javascript">var anotherObject = {      a: 2  };  var myObject = Object.create(anotherObject);  anotherObject.a; // 2  myObject.a; //2  anotherObject.hasOwnProperty("a"); //true  myObject.hasOwnProperty("a"); //false  myObject.a++; //隐式屏蔽  anotherObject.a; //2  myObject.a;//3  myObject.hasOwnProperty("a");//true</code></pre>    <p><strong>构造函数 || 调用</strong></p>    <pre>  <code class="language-javascript">function nosp() {      console.log("don't mind me!");  }  var a = new nosp(); //don't mind me!  a; // {}</code></pre>    <p><strong>委托模式</strong></p>    <pre>  <code class="language-javascript">Task = {      setID: function(ID) {this.id = ID;},      outputID: function() {console.log(this.id);}  };    //让XYZ委托Task  XYZ = Object.create(Task);    XYZ.prepareTask = function(ID, Lable) {      this.setID(ID);      this.Lable = Lable;  };    XYZ.outputTaskDetails = function() {      this.outputID();      console.log(this.Lable);  };</code></pre>    <p>时间有点急,这篇可能有些格式上的问题,以后再看。</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/e6852748ae97</p>    <p> </p>