這一篇文章主要是講述一些有關js的小知識點。由於我也不是很精通哪一方面只能把本身知道的一點點寫出來。取名大雜燴也是這意思吧,既然是道菜那麼就來嚐嚐個人手藝吧。後端
第一道菜數組
1.首先,我想說一下事件綁定。 事件綁定咱們都知道有:on + 'type'
的事件綁定還有addEventListener
的事件綁定。瀏覽器
function bindEvent(obj, type, handle) {
if(window.addEventListener){
obj.addEventListener(type, handle, false);
}
if(window.attachEvent){ // IE
obj.attachEvent('on' + type, handle);
}
obj['on' + type] = handle;
}
複製代碼
on + 'type'
其餘的就是怎麼綁定怎麼解除。function delEvent(obj, type, handle) {
if(window.removeEventListener){
obj.removeEventListener(type, handle, false);
}
if(window.detachEvent){ // IE
obj.attachEvent('on' + type, handle);
}
obj['on' + type] = null;
}
複製代碼
function handle(e){
let event = e || window.event; // IE
let target = e.target || e.srcElement;
}
複製代碼
下一篇我會詳細介紹DOM事件綁定和DOM事件等級。第二道菜bash
2.這個知識點咱們來講一下繼承。app
function Father(){
this.a = 1;
}
Father.prototype.show = function () {
console.log(this.a);
}
function Son(){
Father.call(this);
}
let son = new Son();
console.log(son.a);
console.log(son.show());
複製代碼
function Father(){
this.a = 1;
}
Father.prototype.show = function () {
console.log(this.a);
}
function Son(){
Father.call(this);
}
Son.prototype = Father.prototype; //多了這一行
let son = new Son();
console.log(son.a);
console.log(son.show());
複製代碼
function Father(){
this.a = 1;
}
Father.prototype.show = function () {
console.log(this.a);
}
function Son(){
Father.call(this);
}
function F(){}; //借用中間層來防止Son改變Father的原型
F.prototype = Father.prototype;
Son.prototype = new F();
Son.prototype.constructor = Son; //改變Son的constructor
let son = new Son();
console.log(son.a);
console.log(son.show());
console.log(son.constructor);
複製代碼
function Father(){ this.a = 1; }
這個是否是構造函數?若是說是那你就錯了,由於你思惟固定了。咱們都說構造函數開頭首字母大寫但那只是人爲的規定並非語法。還有若是有人問你
this
是誰,你能夠放肆的告訴他,你沒調用我知道是誰啊。
new
只是一個操做符,任何函數都能經過new來執行,並不僅是構造函數,只不過咱們認爲
new
以後的都是構造函數。
new
的時候發生了什麼嗎?咱們通常都說四步走
function myNew(){
let obj = {};
let Constructor = arguments[0];
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
}
let a = myNew(Son);
console.log(a);
複製代碼
class Father {
constructor(){
this.a = 1;
}
show(){
console.log(this.a);
}
}
class Son extends Father {
constructor(){
super();
}
}
let son = new Son();
console.log(son.a);
console.log(son.show());
複製代碼
class
這種實現方式只是一個‘語法糖’,當咱們用
typeof Son
的時候咱們發現他是一個
function
,其實它就是一個函數只不過更加語義化了,並且裏面定義的方法實際上是定義在了它的原型上面,咱們輸出一下
Father
看看。
第三道菜函數
3.咱們再來介紹一下call、bind、applyui
演示我以爲應該不用了吧,由於我不是在寫文檔,那麼咱們說一些什麼呢,就說說怎麼模擬實現吧。我這裏用的是ES6的語法,我只是以爲這樣寫比較簡單但整體思路不變。 下面以這個爲例:this
var a = 3;
var obj = {
a: 1
}
function show(g) {
console.log(this.a, g);
}
複製代碼
Function.prototype.callh = function(context){
let args = [...arguments].slice(1); //首先獲取到傳遞的參數
context.fn = this; // 獲取當前的調用者,並添加一個方法
context.fn(...args); // 傳入參數
delete context.fn; //刪除新增的函數
}
show.callh(obj, 2);
複製代碼
Function.prototype.applyh = function(context){
let args = arguments[1]; // 跟call同樣,只不過apply傳進來的是數組,因此arguments[1]指的是後面的參數
context.fn = this;
context.fn(...args);
delete context.fn;
show.applyh(obj, [2]);
}
複製代碼
// 簡易版
Function.prototype.bindh = function(context){
let args = [...arguments].slice(1);
let that = this;
return function (argument) { // bind返回一個函數
let args2 = [...arguments].slice(0);
that.call(context, ...args.concat(args2));
}
}
show.bindh(obj)(5);
複製代碼
由於原型的緣由,咱們來改進一下。spa
Function.prototype.bindh = function(context){
let args = [...arguments].slice(1);
let that = this;
function bnd(){}
let fn = function (argument) {
let args2 = [...arguments].slice(0);
return that.call(this instanceof fn ? this : context, ...args.concat(args2));
}
bnd.prototype = this.prototype;
fn.prototype = new bnd();
return fn;
}
複製代碼
這樣就好了。prototype
第四道菜
4.再來說一講this
我想到的差很少就這幾種吧,你或許會發現實際上是按this綁定的優先級升序排序的。若是你看懂了bind的模擬實現也許會知道爲何bind的優先級會高於call、apply。我以爲弄清楚這些this應該不是多大的問題吧,來一段代碼看看。
var a = 3;
var obj = {
a: 1,
fn(){
console.log(this.a);
}
+
}
function show() {
console.log(this.a);
}
show(); //3
obj.fn(); //1
show.call(obj); // 1
show.apply(obj); // 1
show.bind(obj)(); // 1
show.bind(window).call(obj); //3 bind優先級高,跟綁定順序沒區別
複製代碼
但願這些菜能知足您的胃口,希望也能給您填飽一些肚子。我之後還會繼續努力提升本身的廚藝,但願嚐到這個菜的人都會喜歡。