如何手寫new運算符、bind方法、Object.create
1、new 運算符
- 首先咱們本身寫new運算符,沒法寫成 NEW F()這種方法,由於js不識別呀,因此只能將第一個參數看作構造函數,剩餘是其它傳參,例如
let m = NEW(M,'lihaixing',30);
// 等同於js中的
let m = new M('lihaixing',30);
function NEW(){
// 獲取參數
let func = arguments[0]; // 構造函數
let paras = [].slice.call(arguments,1); // 傳入的參數
// 繼承func.prototype的屬性
let o = Object.create(func.prototype);
// 繼承構造函數中的屬性
func.call(o,..paras);
return o;
}
function M (name, age) {
this.name = name;
this.age = age;
}
M.prototype.sayYear = () => {
console.log('2018');
}
let m = NEW(M, 'haixing', 30);
let mm = new M('haixing', 30);
- 在控制檯中依次輸入m, mm, m.sayYear, mm.sayYear調用,結果以下
2、bind方法手寫
- bind方法其實和call很是同樣,惟一的區別就是,call會將函數綁到對象中,而且調用;而bind只是將函數綁到對象中,並不調用,也就是:
f.call(obj)
// 等同於
f.bind(obj)();
- 那麼該怎麼寫呢?咱們知道bind方法是在綁在函數上的,而在js中,每一個函數都是一個new Function(), 也就是和實例對象差很少了,因此咱們要想使每一個函數都能調用bind方法,就應該把它放在Function.prototype中,這樣就是把bind方法寫到了每一個函數的原型中。
Function.prototype.BIND = function () {
// this指向的就是咱們的函數哦
let self = this;
// 獲取參數,因爲return中的函數也有arguments, 這裏需從新賦值一下
let paras = arguments;
return function () {
self.call(...paras); // 不要忘記解構
}
}
let c = {};
let cc = {};
M.BIND(c, 'haixing', 31)();
M.bind(cc, 'haixing', 31)();
- 好像也沒啥問題,可是c和cc是一個字面量對象, 那若是c和cc是構造函數生成的實例對象,那會如何呢?繼續上代碼:
function A (name, age) {
this.name = name;
this.age = age;
}
let d = new A('haixi', 22);
let dd = new A('haixi', 22);
M.BIND(d, 'haixing', 31)();
M.bind(dd, 'haixing', 31)();
- 仍是沒問題哈,constructor也是對的, 那就進入下一環節吧
3、Object.create怎麼寫?
// 這個要簡單一些,就直接寫了
Object.CREATE= function (obj, properties) {
function F () {}
F.prototype = obj;
let o = new F();
// 注意Object.create能夠傳入第二個參數,是一個對象,但格式必須是Object.defineProperties()方法同樣
if (typeof properties === 'object') {
Object.defineProperties(o, properties);
}
return o;
}
let e = Object.create(d, {year: {value: 2019}});
let ee = Object.CREATE(d, {year: {value: 2019}});
- 奇怪哈,爲何一個顯示A一個顯示F呢,但兩個都是A的實例啊?哪位知道,歡迎留言