javascript
javascript中实例对象和构造函数关系、原型语法、原型链、call实现继承、apply调用函数、bind拷贝函数、拷贝继承、class类、super、严格模式、高阶函数、闭包、递归、es6简介
實(shí)例對(duì)象和構(gòu)造函數(shù)的關(guān)系及原型:
實(shí)例對(duì)象是通過(guò)構(gòu)造函數(shù)創(chuàng)建出來(lái)的,實(shí)例對(duì)象的構(gòu)造器constructor就是指向構(gòu)造函數(shù)的;每個(gè)實(shí)例對(duì)象中的同一方法的指向是各不相同的,但是其屬性值相同的屬性可以相同,這樣會(huì)造成內(nèi)存浪費(fèi),可以將這個(gè)方法的函數(shù)提到構(gòu)造函數(shù)的外面,這樣就不會(huì)造成內(nèi)存浪費(fèi)了,但是這種方式容易造成命名問(wèn)題,實(shí)際開(kāi)發(fā)中會(huì)通過(guò)原型來(lái)解決這個(gè)問(wèn)題(原型的作用:共享數(shù)據(jù),節(jié)省內(nèi)存空間,將需要共享的屬性或方法直接寫(xiě)在原型中即可 ),如下:
<script>// 解決多個(gè)對(duì)象中方法指向不同而帶來(lái)內(nèi)存浪費(fèi)問(wèn)題,將方法的函數(shù)提到對(duì)象外:function basketball() {console.log('籃球');};// 構(gòu)造函數(shù):function Person(name, age, height, weight) {this.name = name;this.age = age;this.height = height;this.weight = weight;//對(duì)象中的方法使用構(gòu)造函數(shù)內(nèi)的函數(shù):this.eat = function() {console.log('吃');};//對(duì)象中的方法調(diào)用構(gòu)造函數(shù)外面的函數(shù):this.play = basketball;};// 通過(guò)原型給構(gòu)造函數(shù)添加方法:Person.prototype.song = function() {console.log('可可托海的牧羊人');};var person1 = new Person('jack', 18, 170, 50);var person2 = new Person('杰克', 18, 170, 50);console.log(person1.constructor == Person); //true,對(duì)象的原型指向構(gòu)造函數(shù)console.log(person2.age == person1.age); //true,各個(gè)對(duì)象的屬性值相等的情況下這這兩個(gè)值相同console.log(person2.eat == person1.eat); //false,對(duì)象的方法的函數(shù)寫(xiě)在構(gòu)造函數(shù)中時(shí),各個(gè)對(duì)象的指向不同console.log(person2.basketball == person1.basketball); //true,對(duì)象的方法的函數(shù)寫(xiě)在構(gòu)造函數(shù)外時(shí),各個(gè)對(duì)象的指向相同console.log(person2.song == person1.song); //true,最終要通過(guò)原型的方式給對(duì)象添加相同的方法,實(shí)際開(kāi)發(fā)中采用的方法</script>簡(jiǎn)單原型語(yǔ)法:
給原型添加屬性或者方法可以節(jié)省內(nèi)存空間,共享數(shù)據(jù),但是每次都要通過(guò)prototype的方式多次重復(fù),為此可以將這些屬性或方法通過(guò)對(duì)象的形式寫(xiě)在{}中,但是這種方法需要手動(dòng)寫(xiě)上構(gòu)造器這個(gè)屬性,如:
<script>function Person(names, age) {this.names = names;this.age = age;};// 通過(guò)對(duì)象的方式給原型添加屬性和方法后,前面不能在以普通的方式添加屬性或方法,否則會(huì)報(bào)錯(cuò)或undefined,添加在對(duì)象形式后面是可以的:Person.prototype = {constructor: Person, //手動(dòng)添加構(gòu)造器weight: 49,height: 180,eat: function() {console.log('面條')}};Person.prototype.colors = 'red'; //在對(duì)象形式的后面添加新的屬性或方法是沒(méi)事的Person.prototype.play = function() {console.log('籃球')}; //在對(duì)象形式的后面添加新的屬性或方法是沒(méi)事的var per = new Person('jack', 17);per.eat()console.log(per.weight);console.log(per.colors);per.play();</script>原型中方法可以互相訪問(wèn):
原型中的方法可以互相訪問(wèn),方法中可以調(diào)用屬性;如果要訪問(wèn)一個(gè)屬性或方法,首先會(huì)到實(shí)例對(duì)象中去找,若無(wú)才會(huì)去原型中找。若還是沒(méi)有則返回undefined
<script>function Person(names, age) {this.names = names;this.age = age;};Person.prototype = {constructor: Person, //手動(dòng)添加構(gòu)造器weight: 49,height: 180,eat: function() {console.log('面條');this.song();},song: function() {console.log('可可托海的牧羊人');console.log(this.height);}};var per = new Person('jack', 17);per.eat()console.log(per.colors);</script>內(nèi)置對(duì)象原型中添加方法:
通過(guò)原型的方式可以給內(nèi)置對(duì)象添加自定義方法:
<script>String.prototype.hello = function() {console.log('hello');};var str = new String();str.hello();//給數(shù)組添加求和方法:var arrs = new Array(1, 2, 3);Array.prototype.sums = function() {var sum = 0;for (var i = 0; i < this.length; i++) {sum += this[i];};return sum;};console.log(arrs.sums());</script>將局部變量變成全局變量:
將局部變量變成全局變量的方式:window.變量名 = 值;
原型鏈:
實(shí)例對(duì)象和原型直接的關(guān)系通過(guò)__proto__來(lái)聯(lián)系,這種關(guān)系稱(chēng)為原型鏈。實(shí)例的指向可以通過(guò)proto進(jìn)行改變。
通過(guò)原型繼承屬性或方法:
通過(guò)改變prototype的指向可以繼承父級(jí)的屬性或方法,如:
<script>function Person(names) {this.names = names;};Person.prototype.eat = function() {console.log('吃大米');};function Father(age) {this.age = age;};// 將Father構(gòu)造函數(shù)中的原型指向new Person()實(shí)例對(duì)象中的原型Father.prototype = new Person('jack');Father.prototype.work = function() {console.log('工作');};function Myfather(weight) {this.weight = weight;};// 將Father構(gòu)造函數(shù)中的原型指向new Person()實(shí)例對(duì)象中的原型Myfather.prototype = new Father(30);var myfather = new Myfather(50)console.log(myfather.names + '---' + myfather.age + '---' + myfather.weight);myfather.eat();myfather.work();</script>通過(guò)call借用構(gòu)造函數(shù)實(shí)現(xiàn)繼承:
通過(guò)改變?cè)偷闹赶驅(qū)崿F(xiàn)繼承存在一個(gè)缺陷:改變指向時(shí),初始化了實(shí)例對(duì)象,屬性的值已經(jīng)寫(xiě)死,無(wú)法改變,為了解決這個(gè)缺陷,可以借用構(gòu)造函數(shù)實(shí)現(xiàn)繼承,(call方法的使用:在需要繼承父級(jí)屬性的子級(jí)構(gòu)造函數(shù)中通過(guò):父級(jí)構(gòu)造函數(shù).call(改變函數(shù)this的指向,父級(jí)構(gòu)造函數(shù)中的參數(shù),子級(jí)構(gòu)造函數(shù)中的參數(shù))),子級(jí)構(gòu)造函數(shù)中的形參寫(xiě)上父級(jí)構(gòu)造函數(shù)中的形參,但是這種方式只能繼承屬性,若要繼承方法,那么就要將借用構(gòu)造函數(shù)和改變?cè)拖嘟Y(jié)合,如:
<script>function Person(names, sex) {this.names = names;this.sex = sex;};Person.prototype.eat = function() {console.log('吃飯');};//借用構(gòu)造函數(shù)實(shí)現(xiàn)屬性繼承:function Student(names, sex, score) {Person.call(this, names, sex, score);//第一個(gè)參數(shù)是改變Person中this的指向?yàn)镾tudent構(gòu)造函數(shù)實(shí)例對(duì)象this.score = score;};// 單獨(dú)的借用構(gòu)造函數(shù)只能實(shí)現(xiàn)屬性繼承,方法不能繼承,因此實(shí)際開(kāi)發(fā)中可以將借用構(gòu)造函數(shù)和改變?cè)椭赶蚪Y(jié)合使用:Student.prototype = new Person();var student1 = new Student('jack', '男', 70);var student2 = new Student('sharry', '女', 80);console.log(student1.names, student1.sex, student1.score);console.log(student2.names, student2.sex, student2.score);student1.eat();student2.eat();</script>apply調(diào)用函數(shù):
apply(參數(shù)1,數(shù)組形式參數(shù)2)和call相似,也可以調(diào)用函數(shù)并改變函數(shù)中this的指向,第一個(gè)參數(shù)改變函數(shù)中this的指向,第二個(gè)參數(shù)以數(shù)組的形式傳參數(shù),返回的是字符串形式的值;但是apply的主要用法是調(diào)用內(nèi)置對(duì)象方法來(lái)實(shí)現(xiàn)某些函數(shù)中沒(méi)有的方法的功能,如:
<script>// 實(shí)現(xiàn)call方法的作用:var obj = {weight: 120};function fn(x, y, z) {console.log(this); //{weight: 120}console.log(x, y, z); //age 12 names};fn.apply(obj, ['age', 12, 'names']);// 如借用Math中min方法來(lái)實(shí)現(xiàn)求數(shù)組中最小值:var array = [2, 3, 4, 1]var minValue = Math.min.apply(null, array); //當(dāng)一個(gè)形參不需要實(shí)參時(shí)可以用null代替,這里最好將指向指為apply的調(diào)用者console.log(minValue); //1console.log(Math.max(2, 3, 4, 1)); //4,Math對(duì)象中求最大值最小值的方法中傳入的是數(shù)字</script>bind拷貝函數(shù):
fn.bind(參數(shù)1,參數(shù)2),不會(huì)調(diào)用原函數(shù),但是可以通過(guò)第一個(gè)參數(shù)改變函數(shù)this的指向并返回一個(gè)新函數(shù);此方法不會(huì)立即執(zhí)行函數(shù),而call和apply都會(huì)立即執(zhí)行行數(shù),因此bind在實(shí)際開(kāi)發(fā)中用的會(huì)比較多。
拷貝繼承:
淺拷貝:指的是地址的拷貝;深拷貝:指完全的把堆上的代碼也拷貝,但是地址不拷貝。
<script>var obj1 = {names: 'jack',age: 18};// 1.通過(guò)改變指針實(shí)現(xiàn)拷貝繼承:var obj2 = obj1;console.log(obj2.names);// 2.通過(guò)for-in遍歷將obj1的屬性和值存到obj3中:var obj3 = {};for (var key in obj1) {obj3[key] = obj1[key];};console.log(obj3.names);// 3.通過(guò)遍歷原型的屬性和方法拷貝對(duì)象:var obj4 = {};function Person() {};Person.prototype.names = 'sharry';Person.prototype.eat = function() {console.log('面條');};var person = new Person('sharry');for (var keys in Person.prototype) {obj4[keys] = Person.prototype[keys];};console.log(obj4.names);obj4.eat();</script>構(gòu)造函數(shù)、實(shí)例對(duì)象、原型之間的關(guān)系:
通過(guò)class來(lái)創(chuàng)建對(duì)象:
class類(lèi)指的是一類(lèi)具有相似屬性或方法的事物,通過(guò)new也可以創(chuàng)建實(shí)例對(duì)象,其語(yǔ)法是:class 類(lèi)名{},class類(lèi)的大括號(hào)中要寫(xiě)構(gòu)造器:constructor(形參){this.屬性或方法},但是實(shí)際開(kāi)發(fā)中不建議將方法寫(xiě)在構(gòu)造器中,而是省去關(guān)鍵字function直接寫(xiě)在class類(lèi)中,之后通過(guò)new實(shí)例化對(duì)象,如:
<script>class Person {constructor(names, age) {this.names = names;this.age = age;// 方法不建議這樣寫(xiě):this.eat = function() {console.log('面條')};};// 類(lèi)中的方法建議寫(xiě)在類(lèi)中:play() {console.log('籃球')};};var personOne = new Person('jack', 18);console.log('names:' + personOne.names + '---age:' + personOne.age);personOne.eat();personOne.play();</script>class類(lèi)的繼承:
class類(lèi)可以繼承一個(gè)類(lèi)的屬性和方法,其語(yǔ)法:class 新類(lèi)名 extends 被繼承類(lèi)名 {};之后通過(guò)new實(shí)例化對(duì)象即可,如:
<script>class Person {constructor(names) {this.names = names;this.eat = function() {console.log('面條')};};play() {console.log('籃球')};};// 繼承class Son extends Person {};var sonOne = new Son('jack');console.log(sonOne.names);sonOne.eat();sonOne.play();</script>super()調(diào)用父級(jí)類(lèi)中的構(gòu)造器:
被繼承后的類(lèi),若要調(diào)用父級(jí)的方法,而方法中有參數(shù),此時(shí)給子級(jí)實(shí)例對(duì)象傳入?yún)?shù)是無(wú)法被父級(jí)中的方法中拿到的,此時(shí)需要給子級(jí)構(gòu)造器中通過(guò)super(參數(shù))將子級(jí)實(shí)例對(duì)象中的參數(shù)傳給父級(jí)構(gòu)造器,super還可以調(diào)用父類(lèi)中的父類(lèi)中的普通方法,如:
<script>class Person {constructor(x, y) {this.x = x;this.y = y;};sum() {return this.x + this.y;};play() {console.log('籃球');};};class Son extends Person {constructor(a, b) {// 這里不能直接通過(guò)this來(lái)設(shè)置屬性接收參數(shù),而要通過(guò)super()調(diào)用父級(jí)中的構(gòu)造器,才能調(diào)用父級(jí)的方法:super(a, b);//必須在this接收參數(shù)之前調(diào)用super// this.a = a;//這里的this.參數(shù) 是給自己的方法準(zhǔn)備的參數(shù),自己的方法調(diào)用時(shí)需要接收的參數(shù)// this.b = b;}play() {super.play();console.log('排球');}; };var sonOne = new Son(1, 2);console.log(sonOne.sum());sonOne.play(); //方法的調(diào)用首先會(huì)先 從自己的類(lèi)中找,若沒(méi)有則去父級(jí)類(lèi)中找,若還是沒(méi)有會(huì)報(bào)錯(cuò),其中有則執(zhí)行方法(就近原則)</script>開(kāi)啟嚴(yán)格模式:
嚴(yán)格模式在IE10以上版本才支持,消除了javascript中的一些問(wèn)題寫(xiě)法;若要給某個(gè)作用域開(kāi)啟嚴(yán)格模式,則在該作用域?qū)懭胍韵麓a即可:
'use strict';//用來(lái)開(kāi)啟嚴(yán)格模式:嚴(yán)格模式指的是書(shū)寫(xiě)代碼必須按照代碼規(guī)范,不能省略代碼高階函數(shù):
高階函數(shù)是對(duì)其他函數(shù)進(jìn)行操作的函數(shù),它接受的參數(shù)是函數(shù)或返回的是函數(shù)。
<script>function f1(callback) {callback && callback();};f1(function f2() {console.log('這是高階函數(shù)')});</script>閉包:
閉包指:有權(quán)訪問(wèn)另一函數(shù)作用域中變量的函數(shù)(在普通函數(shù)中是無(wú)法訪問(wèn)到其他作用域的變量的),其作用是延伸了變量的作用范圍,
<script>function f() {var str = '123';function f2() {console.log(str);};return f2;};var result = f(); //這里的f接收的是f2函數(shù),相當(dāng)于在f外面打印str,高階函數(shù)實(shí)現(xiàn)閉包result();</script><script>// 利用閉包打印出li的類(lèi)容:類(lèi)似這種問(wèn)題可以采用:for循環(huán)里面首先放入自執(zhí)行函數(shù),自執(zhí)行函數(shù)里面寫(xiě)入處理業(yè)務(wù)的代碼// 通過(guò)遍歷將循環(huán)里面的所有代碼存到內(nèi)存中,等定時(shí)器啟動(dòng)后,執(zhí)行業(yè)務(wù)代碼,閉包也有壞處var liList = document.querySelectorAll('li');for (var i = 0; i < liList.length; i++) {(function(x) {var ids = setInterval(function() {console.log(liList[x].innerHTML);clearInterval(ids);}, 2000);})(i);};</script>遞歸:
遞歸指:一個(gè)函數(shù)在內(nèi)部可以調(diào)用自己本身,那么這個(gè)函數(shù)就是自己,由于遞歸可能出現(xiàn)死循環(huán)發(fā)生棧溢出,所以必須要加退出條件return。
<script>var i = 0;function f() {console.log(i);if (i > 5) {return;};i++;f();};f();</script>es6內(nèi)容簡(jiǎn)介:
關(guān)鍵字let、const:
let關(guān)鍵字是es6中聲明變量的,其作用和var相似,let聲明的變量只在塊級(jí)有效,塊級(jí)作用域指{}里面,沒(méi)有變量提升,必須先聲明后使用,具有暫時(shí)性死區(qū)性(使用一個(gè)變量先從本塊級(jí)作用域查找,有則使用,注意變量沒(méi)有提升,MDN文檔中有變量提升,但是會(huì)拋出錯(cuò)誤)。
const關(guān)鍵字是es6中聲明常量的,因此若要改變這個(gè)關(guān)鍵字聲明的常量,就會(huì)報(bào)錯(cuò),它也是在塊級(jí)有效,變量不會(huì)提升,MDN文檔中有變量提升,但是會(huì)拋出錯(cuò)誤。
<script>if (true) {var num1 = '1';console.log(num1); //1};if (true) {let num2 = '2';console.log(num2); //2};if (true) {const num3 = '3';console.log(num3); //3};console.log(num1); //1console.log(num2); //num2 is not definedconsole.log(num3); //num3 is not defined</script>解構(gòu)賦值:
es6中允許從數(shù)組或?qū)ο笾刑崛≈?#xff0c;按照對(duì)應(yīng)位置,對(duì)變量賦值;對(duì)象中每個(gè)屬性名和前面屬性名一致;若在對(duì)象中,前面也是鍵值對(duì)的形式,那么這值實(shí)際是變量,接收的是對(duì)應(yīng)的后面對(duì)象張的值,如:
<script>var [a, b, c] = [1, 2, 3];var {d,e,f}={d:4,e:5,f:6};var {dn: num1,en: num2,fn: num3} = {dn: 4,en: 5,fn: 6};console.log(b);//2console.log(e);//5console.log(num2); //5</script>箭頭函數(shù):
箭頭函數(shù)是es6中另一種寫(xiě)法,其作用和普通函數(shù)一樣,只是在書(shū)寫(xiě)上比較簡(jiǎn)潔了。箭頭函數(shù)沒(méi)有函數(shù)名,因此通常用變量接收,如:const fn =()=>{};,小括號(hào)中可以傳入形參;箭頭函數(shù)中的this不指向調(diào)用者,而指函數(shù)定義位置的上下文中this即:箭頭函數(shù)所在作用域中的this
<script>var sum = (x, y) => {console.log(x + y);};sum(2, 3); //5// 當(dāng)函數(shù)體中只有一句執(zhí)行代碼,且這行代碼就是函數(shù)的返回值,此時(shí)可以省略{}:var sum1 = (x, y) => console.log(x + y);sum1(1, 2); //3// 當(dāng)函數(shù)的形參只有一個(gè)的時(shí)候可以省略():const num = x => console.log(x);num(5); //5</script>剩余參數(shù):
當(dāng)函數(shù)的實(shí)參大于一個(gè)形參的個(gè)數(shù)時(shí),給形參最后一個(gè)參數(shù)見(jiàn)面加…后(當(dāng)然可以給第一個(gè)形參直接加…,此時(shí)將傳入的實(shí)參以數(shù)組的形式返回),剩余的實(shí)參則會(huì)以數(shù)組的形式存在最后一個(gè)形參里面:
<script>function num(num1, num2, ...numn) {console.log(numn);};num(1, 2, 3, 4); //[3, 4]// 剩余參數(shù)和解構(gòu)配合:var [num1, ...num] = [1, 2, 3, 4, 5];console.log(num); //[2, 3, 4, 5]</script>擴(kuò)展運(yùn)算符:
擴(kuò)展運(yùn)算符可將數(shù)組或?qū)ο筠D(zhuǎn)為用逗號(hào)分隔的參數(shù)序列,其語(yǔ)法是在變量名前面加…,如:
<script>var arr = [1, 2, 3];console.log(...arr); //1 2 3,原本...arr里面是用逗號(hào)隔開(kāi)的,但是這里是因?yàn)閏onsole.log將里面的逗號(hào)當(dāng)做分隔符了。//擴(kuò)展運(yùn)算符可以將多個(gè)數(shù)組合并:var arr1 = [1, 2, 3];var arr2 = [4, 5];var arr3 = [6];var arrn = [...arr1, ...arr2, ...arr3];console.log(arrn); //[1, 2, 3, 4, 5, 6]// 利用擴(kuò)展運(yùn)算符將偽數(shù)組轉(zhuǎn)換為真數(shù)組:其語(yǔ)法:[...偽數(shù)組變量名]</script>模板字符串:
使用反引號(hào)的字符串稱(chēng)之為模板字符串,可以很好地將變量解析到字符串中的語(yǔ)法,其語(yǔ)法:在反引號(hào)中使用(${變量名}),模板字符串支持換行,支持調(diào)用函數(shù)如:
<script>var num = 2;var str = `今天是${num}號(hào)`;console.log(str);// 調(diào)用函數(shù)和換行:var say = () => {return 'hello'};var sayhe = `${say()}word`;console.log(sayhe);</script>Set數(shù)據(jù)結(jié)構(gòu):
Set數(shù)據(jù)結(jié)構(gòu)類(lèi)似數(shù)組,但是成員的值都是唯一的(當(dāng)傳入的數(shù)據(jù)中有重復(fù)的值時(shí),會(huì)自動(dòng)將重復(fù)值去掉),其是一個(gè)構(gòu)造函數(shù),需要實(shí)例化對(duì)象才能使用:const sets = new Set();此對(duì)象可以接收一個(gè)數(shù)組,數(shù)組中的數(shù)據(jù)會(huì)被自動(dòng)存到set數(shù)據(jù)結(jié)構(gòu)中;支持forEach遍歷set數(shù)據(jù):
<script>var sets = new Set([1, 2, 2]);console.log(sets.size); //2,size屬性用來(lái)獲取set中存的不重復(fù)值的個(gè)數(shù),和length類(lèi)似。// 給sets增加數(shù)據(jù):add(value)sets.add(3);console.log(sets); //Set(3) {1, 2, 3}//刪除sets數(shù)據(jù)中的值:delete(value),并返回一個(gè)布爾值用于判斷是否刪除成功:var result = sets.delete(1);console.log(result); //trueconsole.log(sets); //Set(2) {2, 3}// 判斷某個(gè)值是否是sets中的成員:has(value),返回一個(gè)布爾值var results = sets.has(7);console.log(results); //false// 清空sets中的數(shù)據(jù):clear():sets.clear();console.log(sets);//Set(0) {}</script>數(shù)組查詢(xún):find和findindex:
在es6中,js為數(shù)組提供了一個(gè)遍歷數(shù)組查詢(xún)某項(xiàng)的API:find-----需要傳入一個(gè)函數(shù)作為參數(shù);同樣在es6中js為數(shù)組提供了一個(gè)遍歷數(shù)組查詢(xún)某項(xiàng)下標(biāo)的API:findIndex—也需要傳入一個(gè)函數(shù)作為參數(shù),如下案例:
提示:本文圖片等素材來(lái)源于網(wǎng)絡(luò),若有侵權(quán),請(qǐng)發(fā)郵件至郵箱:810665436@qq.com聯(lián)系筆者 刪除。
筆者:苦海
總結(jié)
以上是生活随笔為你收集整理的javascript中实例对象和构造函数关系、原型语法、原型链、call实现继承、apply调用函数、bind拷贝函数、拷贝继承、class类、super、严格模式、高阶函数、闭包、递归、es6简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python enumeration_p
- 下一篇: jQuery中的ajax、jquery中