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

this在調(diào)用時綁定,完全取決于函數(shù)的調(diào)用位置。
綁定規(guī)則

  1. 默認(rèn)綁定(獨立函數(shù)調(diào)用,綁定到全局對象,但嚴(yán)格模式下this會綁定到undefined)
function foo() {
    console.log(this.a);
}
var a = 2;
foo(); // 2
  1. 隱式綁定:當(dāng)函數(shù)引用有上下文對象時,this綁定在這個上下文對象上,最后一層調(diào)用位置起作用
function foo() {
    console.log(this.a);
}
var obj = {
    a: 2,
    foo: foo
}
var a = "hello";
obj.foo(); // 2

隱式丟失

function foo() {
    console.log(this.a);
}
var obj = {
    a: 2,
    foo: foo
}
var bar = obj.foo; //實際上指向foo本身,獨立函數(shù)調(diào)用
var a = "hello world";
bar(); // hello world
  1. 顯示綁定,call和apply,第一個參數(shù)是對象,函數(shù)調(diào)用時將this綁定到這個對象上
    硬綁定
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
  1. new綁定:用new調(diào)用函數(shù)時,會創(chuàng)建一個新對象,并將這個新對象綁定到函數(shù)調(diào)用的this上。
function foo(a) {
    this.a = a;
}
var bar = new foo(2); //將返回的對象bar綁定在foo的this上
console.log(bar.a); //2

綁定規(guī)則優(yōu)先級

  1. 顯示綁定高于隱式綁定
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調(diào)用
obj2.foo.call(obj1);//2
  1. new綁定高于隱式綁定
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
  1. new綁定高于硬綁定(new 和call或者apply不能同時使用)
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

new中使用硬綁定,可以預(yù)先設(shè)置一些參數(shù),使用new初始化時只需傳入其他的參數(shù),柯里化的一種

function foo(p1, p2) {
    this.val = p1 + p2;
}
var bar = foo.bind(null, "p1"); //不關(guān)心硬綁定到哪里,this會被new修改
var baz = new bar("p2");
console.log(baz.val);//p1p2

綁定例外
把null或者undefined傳入call,apply,bind等,忽略this

function foo() {
    console.log(this.a);
}
var a = 2;
foo.call(null);//2,實際使用默認(rèn)綁定

間接引用

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,返回值是目標(biāo)函數(shù)的引用,所以是默認(rèn)綁定

軟綁定

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

箭頭函數(shù):根據(jù)外層作用域來決定this,箭頭函數(shù)的綁定無法修改

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

數(shù)組,添加數(shù)字類屬性,數(shù)組長度增加

var myArray = ["foo", 42, "bar"];
myArray.baz = "baz";
console.log(myArray.length);
myArray["3"] = "baz";
console.log(myArray.length);

屬性描述符:writable,是否可以修改屬性的值;configurable,屬性描述符是否可修改,為false的話禁止刪除這個屬性;Enumerable,可枚舉
getter / setter

var myObject = {
    get a() {
        return this._a_;
    },
    set a(val) {
        this._a_ = val * 2; 
    }
};
myObject.a = 2;
console.log(myObject.a);

屬性的存在性,值為undefined或者不存在都返回

undefined
var myObject = {
    a:2
};
"a" in myObject; // true, 會檢查原型鏈
"b" in myObject; //false
myObject.hasOwnProperty("a");//true,只檢查對象本身
myObject.hasOwnProperty("b");//false

混入

1、 顯示混入

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!");
    }
});

2、混合混入,先進行復(fù)制,之后再特殊化,效率低,不常用

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);

3、寄生繼承

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();

4、 隱式混入

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 不是共享狀態(tài)

隱式屏蔽

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

構(gòu)造函數(shù) || 調(diào)用

function nosp() {
    console.log("don't mind me!");
}
var a = new nosp(); //don't mind me!
a; // {} 

委托模式

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);
};

時間有點急,這篇可能有些格式上的問題,以后再看。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容