摘要:前言這段時間突然發(fā)現(xiàn)原生好多東西都忘記了但有些東西確實很重要所以又重新再梳理一次。
前言
這段時間突然發(fā)現(xiàn)JS原生好多東西都忘記了,但有些東西確實很重要,所以又重新再梳理一次。主要有函數(shù)的3種定義方法,ES5函數(shù)this指向,call與appl用法,JS常見的4種設(shè)計模式,原型鏈,原型鏈和繼承的方式(ES5和ES6)1.函數(shù)的3種定義方法 1.1 函數(shù)聲明
//ES5 function getSum(){} function (){}//匿名函數(shù) //ES6 ()=>{}//如果{}內(nèi)容只有一行{}和return關(guān)鍵字可省,1.2 函數(shù)表達式(函數(shù)字面量)
//ES5 var sum=function(){} //ES6 let sum=()=>{}//如果{}內(nèi)容只有一行{}和return關(guān)鍵字可省,1.3 構(gòu)造函數(shù)
var sum=new GetSum(num1,num2)1.4 三種方法的對比
1.函數(shù)聲明有預(yù)解析,而且函數(shù)聲明的優(yōu)先級高于變量;
2.使用Function構(gòu)造函數(shù)定義函數(shù)的方式是一個函數(shù)表達式,這種方式會導(dǎo)致解析兩次代碼,影響性能。第一次解析常規(guī)的JavaScript代碼,第二次解析傳入構(gòu)造函數(shù)的字符串
在ES5中函數(shù)內(nèi)容的this指向和調(diào)用方法有關(guān)
2.1 函數(shù)調(diào)用模式包括函數(shù)名()和匿名函數(shù)調(diào)用,this指向window
function getSum() { console.log(this) //window } getSum() (function() { console.log(this) //window })() var getSum=function() { console.log(this) //window } getSum()2.2 方法調(diào)用
對象.方法名(),this指向?qū)ο?/p>
var objList = { name: "methods", getSum: function() { console.log(this) //objList對象 } } objList.getSum()2.3 構(gòu)造器調(diào)用
new 構(gòu)造函數(shù)名(),this指向構(gòu)造函數(shù)
function Person() { console.log(this); //指向構(gòu)造函數(shù)Person } var personOne = new Person();2.4 間接調(diào)用
利用call和apply來實現(xiàn),this就是call和apply對應(yīng)的第一個參數(shù),如果不傳值或者第一個值為null,undefined時this指向window
function foo() { console.log(this); } foo.apply("我是apply改變的this值");//我是apply改變的this值 foo.call("我是call改變的this值");//我是call改變的this值3.ES6中函數(shù)的調(diào)用
箭頭函數(shù)不可以當作構(gòu)造函數(shù)使用,也就是不能用new命令實例化一個對象,否則會拋出一個錯誤
箭頭函數(shù)的this是和定義時有關(guān)和調(diào)用無關(guān)
調(diào)用就是函數(shù)調(diào)用模式
(() => { console.log(this)//window })() let arrowFun = () => { console.log(this)//window } arrowFun() let arrowObj = { arrFun: function() { (() => { console.log(this)//arrowObj })() } } arrowObj.arrFun();4.call,apply和bind
1.IE5之前不支持call和apply,bind是ES5出來的;
2.call和apply可以調(diào)用函數(shù),改變this,實現(xiàn)繼承和借用別的對象的方法;
調(diào)用方法,用一個對象替換掉另一個對象(this)
對象.call(新this對象,實參1,實參2,實參3.....)
對象.apply(新this對象,[實參1,實參2,實參3.....])
1.間接調(diào)用函數(shù),改變作用域的this值
2.劫持其他對象的方法
var foo = { name:"張三", logName:function(){ console.log(this.name); } } var bar={ name:"李四" }; foo.logName.call(bar);//李四 實質(zhì)是call改變了foo的this指向為bar,并調(diào)用該函數(shù)
3.兩個函數(shù)實現(xiàn)繼承
function Animal(name){ this.name = name; this.showName = function(){ console.log(this.name); } } function Cat(name){ Animal.call(this, name); } var cat = new Cat("Black Cat"); cat.showName(); //Black Cat
4.為類數(shù)組(arguments和nodeList)添加數(shù)組方法push,pop
(function(){ Array.prototype.push.call(arguments,"王五"); console.log(arguments);//["張三","李四","王五"] })("張三","李四")
5.合并數(shù)組
let arr1=[1,2,3]; let arr2=[4,5,6]; Array.prototype.push.apply(arr1,arr2); //將arr2合并到了arr1中
6.求數(shù)組最大值
Math.max.apply(null,arr)
7.判斷字符類型
Object.prototype.toString.call({})4.3 bind
bind是function的一個函數(shù)擴展方法,bind以后代碼重新綁定了func內(nèi)部的this指向,不會調(diào)用方法,不兼容IE8
var name = "李四" var foo = { name: "張三", logName: function(age) { console.log(this.name, age); } } var fooNew = foo.logName; var fooNewBind = foo.logName.bind(foo); fooNew(10)//李四,10 fooNewBind(11)//張三,11 因為bind改變了fooNewBind里面的this指向4.4 call,apply和bind原生實現(xiàn)
call實現(xiàn):
Function.prototype.newCall = function(context, ...parameter) { context.fn = this; context.fn(...parameter); delete context.fn; } let person = { name: "Abiel" } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, "男"); // Abiel 25 男
apply實現(xiàn):
Function.prototype.newApply = function(context, parameter) { if (typeof context === "object") { context = context || window } else { context = Object.create(null) } let fn = Symbol() context[fn] = this context[fn](parameter); delete context[fn] }
bind實現(xiàn):
Function.prototype.bind = function (context,...innerArgs) { var me = this return function (...finnalyArgs) { return me.call(context,...innerArgs,...finnalyArgs) } } let person = { name: "Abiel" } function sayHi(age,sex) { console.log(this.name, age, sex); } let personSayHi = sayHi.bind(person, 25) personSayHi("男")4.5 三者異同
同:都是改變this指向,都可接收參數(shù)
異:bind和call是接收單個參數(shù),apply是接收數(shù)組
類型 | 概念 | 應(yīng)用 |
---|---|---|
節(jié)流 | 某個時間段內(nèi),只執(zhí)行一次 | 滾動條,resize事件一段時間觸發(fā)一次 |
防抖 | 處理函數(shù)截止后一段時間依次執(zhí)行 | scroll,resize事件觸發(fā)完后一段時間觸發(fā) |
節(jié)流:
5.1 節(jié)流let throttle = function(func, delay) { let timer = null; return function() { if (!timer) { timer = setTimeout(function() { func.apply(this, arguments); timer = null; }, delay); } }; }; function handle() { console.log(Math.random()); } window.addEventListener("scroll", throttle(handle, 1000)); //事件處理函數(shù)5.2 防抖
function debounce(fn, wait) { var timeout = null; return function() { if (timeout !== null) clearTimeout(timeout);//如果多次觸發(fā)將上次記錄延遲清除掉 timeout = setTimeout(function() { fn.apply(this, arguments); timer = null; }, wait); }; } // 處理函數(shù) function handle() { console.log(Math.random()); } // 滾動事件 window.addEventListener("onscroll", debounce(handle, 1000));6.原型鏈 6.1 定義
對象繼承屬性的一個鏈條
6.2構(gòu)造函數(shù),實例與原型對象的關(guān)系var Person = function (name) { this.name = name; }//person是構(gòu)造函數(shù) var o3personTwo = new Person("personTwo")//personTwo是實例
原型對象都有一個默認的constructor屬性指向構(gòu)造函數(shù)
6.3 創(chuàng)建實例的方法1.字面量
let obj={"name":"張三"}
2.Object構(gòu)造函數(shù)創(chuàng)建
let Obj=new Object() Obj.name="張三"
3.使用工廠模式創(chuàng)建對象
function createPerson(name){ var o = new Object(); o.name = name; }; return o; } var person1 = createPerson("張三");
4.使用構(gòu)造函數(shù)創(chuàng)建對象
function Person(name){ this.name = name; } var person1 = new Person("張三");6.4 new運算符
1.創(chuàng)了一個新對象;
2.this指向構(gòu)造函數(shù);
3.構(gòu)造函數(shù)有返回,會替換new出來的對象,如果沒有就是new出來的對象
4.手動封裝一個new運算符
var new2 = function (func) { var o = Object.create(func.prototype); //創(chuàng)建對象 var k = func.call(o); //改變this指向,把結(jié)果付給k if (typeof k === "object") { //判斷k的類型是不是對象 return k; //是,返回k } else { return o; //不是返回返回構(gòu)造函數(shù)的執(zhí)行結(jié)果 } }
更多詳情:詳談JavaScript原型鏈
6.5 對象的原型鏈 7.繼承的方式JS是一門弱類型動態(tài)語言,封裝和繼承是他的兩大特性
7.1原型鏈繼承將父類的實例作為子類的原型
1.代碼實現(xiàn)
定義父類:
// 定義一個動物類 function Animal (name) { // 屬性 this.name = name || "Animal"; // 實例方法 this.sleep = function(){ console.log(this.name + "正在睡覺!"); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + "正在吃:" + food); };
子類:
function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = "cat"; // Test Code var cat = new Cat(); console.log(cat.name);//cat console.log(cat.eat("fish"));//cat正在吃:fish undefined console.log(cat.sleep());//cat正在睡覺! undefined console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
2.優(yōu)缺點
簡單易于實現(xiàn),但是要想為子類新增屬性和方法,必須要在new Animal()這樣的語句之后執(zhí)行,無法實現(xiàn)多繼承
實質(zhì)是利用call來改變Cat中的this指向
1.代碼實現(xiàn)
子類:
function Cat(name){ Animal.call(this); this.name = name || "Tom"; }
2.優(yōu)缺點
可以實現(xiàn)多繼承,不能繼承原型屬性/方法
為父類實例添加新特性,作為子類實例返回
1.代碼實現(xiàn)
子類
function Cat(name){ var instance = new Animal(); instance.name = name || "Tom"; return instance; }
2.優(yōu)缺點
不限制調(diào)用方式,但不能實現(xiàn)多繼承
將父類的屬性和方法拷貝一份到子類中
1.子類:
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || "Tom"; }
2.優(yōu)缺點
支持多繼承,但是效率低占用內(nèi)存
通過調(diào)用父類構(gòu)造,繼承父類的屬性并保留傳參的優(yōu)點,然后通過將父類實例作為子類原型,實現(xiàn)函數(shù)復(fù)用
1.子類:
function Cat(name){ Animal.call(this); this.name = name || "Tom"; } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat;7.6 寄生組合繼承
function Cat(name){ Animal.call(this); this.name = name || "Tom"; } (function(){ // 創(chuàng)建一個沒有實例方法的類 var Super = function(){}; Super.prototype = Animal.prototype; //將實例作為子類的原型 Cat.prototype = new Super(); })();7.7 ES6的extends繼承
ES6 的繼承機制是先創(chuàng)造父類的實例對象this(所以必須先調(diào)用super方法),然后再用子類的構(gòu)造函數(shù)修改this,鏈接描述
//父類 class Person { //constructor是構(gòu)造方法 constructor(skin, language) { this.skin = skin; this.language = language; } say() { console.log("我是父類") } } //子類 class Chinese extends Person { constructor(skin, language, positon) { //console.log(this);//報錯 super(skin, language); //super();相當于父類的構(gòu)造函數(shù) //console.log(this);調(diào)用super后得到了this,不報錯,this指向子類,相當于調(diào)用了父類.prototype.constructor.call(this) this.positon = positon; } aboutMe() { console.log(`${this.skin} ${this.language} ${this.positon}`); } } //調(diào)用只能通過new的方法得到實例,再調(diào)用里面的方法 let obj = new Chinese("紅色", "中文", "香港"); obj.aboutMe(); obj.say();
更多詳情請戳:JS繼承的實現(xiàn)方式
8.高階函數(shù) 8.1定義函數(shù)的參數(shù)是函數(shù)或返回函數(shù)
8.2 常見的高階函數(shù)map,reduce,filter,sort
8.3 柯里化1.定義:只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個函數(shù)去處理剩下的參數(shù)
fn(a,b,c,d)=>fn(a)(b)(c)(d)
2.代碼實現(xiàn):
let currying = function(fn) { // args 獲取第一個方法內(nèi)的全部參數(shù) var args = Array.prototype.slice.call(arguments, 1) return function() { // 將后面方法里的全部參數(shù)和args進行合并 var newArgs = args.concat(Array.prototype.slice.call(arguments)) // 把合并后的參數(shù)通過apply作為fn的參數(shù)并執(zhí)行 return fn.apply(this, newArgs) } }8.4 反柯里化
1.定義:
obj.func(arg1, arg2)=>func(obj, arg1, arg2)
2.代碼實現(xiàn):
Function.prototype.uncurrying = function() { var that = this; return function() { return Function.prototype.call.apply(that, arguments); } }; function sayHi () { return "Hello " + this.value +" "+[].slice.call(arguments); } let sayHiuncurrying=sayHi.uncurrying(); console.log(sayHiuncurrying({value:"world"},"hahaha"));8.5偏函數(shù)
1.定義:指定部分參數(shù)來返回一個新的定制函數(shù)的形式
2.例子:
function foo(a, b, c) { return a + b + c; } function func(a, b) { return foo(a,b,8); }參考文獻:
https://www.cnblogs.com/tugen...
https://www.cnblogs.com/humin...
https://www.cnblogs.com/cheng...
https://www.cnblogs.com/cheng...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94286.html
摘要:模塊模式概念模式最初被定義為一種在傳統(tǒng)軟件工程中為類提供私有和共有封裝的方法。應(yīng)用將暴露的公有指針指向到私有函數(shù)和屬性上參考設(shè)計模式設(shè)計模式系列文章設(shè)計模式之工廠模式設(shè)計模式之單例模式設(shè)計模式之外觀模式設(shè)計模式之模塊模式揭示模塊模式 Module(模塊)模式 概念 Module模式最初被定義為一種在傳統(tǒng)軟件工程中為類提供私有和共有封裝的方法。 通過這種方式,能夠使一個單獨的對象擁有共有...
摘要:實際上就是做了這樣一件事情顯式的指定是回顧一下隱式模式顯示模式觀點里所有函數(shù)都接受個參數(shù)第一個第二個是函數(shù)被調(diào)用時一定會有這個參數(shù)如果你用調(diào)用函數(shù)就是顯式的傳遞和如果你用語法直接調(diào)用函數(shù)那就去幫你偷偷的傳遞。 JS面向?qū)ο笾総his】 (對象和函數(shù)之間的關(guān)系) 上一篇,談了對象和對象的關(guān)系,現(xiàn)在我們談?wù)剬ο蠛秃瘮?shù)的關(guān)系 先說結(jié)論,也就是觀點1 觀點1: JS里函數(shù)和對象沒有關(guān)系,J...
摘要:好程序員前端培訓(xùn)入門之基礎(chǔ)知識梳理匯總,前端工程師是當前各大企業(yè)都比較稀缺的人才,薪資待遇和就業(yè)前景都很不錯。作用域鏈的前端,始終是當前執(zhí)行代碼所在環(huán)境的變量對象。 好程序員Web前端培訓(xùn)入門之JS基礎(chǔ)知識梳理匯總,Web前端工程師是當前各大企業(yè)都比較稀缺的人才,薪資待遇和就業(yè)前景都很不錯。不論是專業(yè)還是非專業(yè),有基礎(chǔ)亦或是無基礎(chǔ),都想通過學(xué)習(xí)Web前端實現(xiàn)高薪就業(yè)。不過,學(xué)習(xí)要一...
摘要:好程序員前端培訓(xùn)入門之基礎(chǔ)知識梳理匯總,前端工程師是當前各大企業(yè)都比較稀缺的人才,薪資待遇和就業(yè)前景都很不錯。作用域鏈的前端,始終是當前執(zhí)行代碼所在環(huán)境的變量對象。 好程序員Web前端培訓(xùn)入門之JS基礎(chǔ)知識梳理匯總,Web前端工程師是當前各大企業(yè)都比較稀缺的人才,薪資待遇和就業(yè)前景都很不錯。不論是專業(yè)還是非專業(yè),有基礎(chǔ)亦或是無基礎(chǔ),都想通過學(xué)習(xí)Web前端實現(xiàn)高薪就業(yè)。不過,學(xué)習(xí)要一...
閱讀 3106·2021-11-18 10:02
閱讀 2618·2021-10-13 09:47
閱讀 3034·2021-09-22 15:07
閱讀 791·2019-08-30 15:43
閱讀 1810·2019-08-30 10:59
閱讀 1685·2019-08-29 15:34
閱讀 1702·2019-08-29 15:06
閱讀 439·2019-08-29 13:28