日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

javascript中实例对象和构造函数关系、原型语法、原型链、call实现继承、apply调用函数、bind拷贝函数、拷贝继承、class类、super、严格模式、高阶函数、闭包、递归、es6简介

發布時間:2025/3/15 javascript 21 豆豆

實例對象和構造函數的關系及原型:

實例對象是通過構造函數創建出來的,實例對象的構造器constructor就是指向構造函數的;每個實例對象中的同一方法的指向是各不相同的,但是其屬性值相同的屬性可以相同,這樣會造成內存浪費,可以將這個方法的函數提到構造函數的外面,這樣就不會造成內存浪費了,但是這種方式容易造成命名問題,實際開發中會通過原型來解決這個問題(原型的作用:共享數據,節省內存空間,將需要共享的屬性或方法直接寫在原型中即可 ),如下:

<script>// 解決多個對象中方法指向不同而帶來內存浪費問題,將方法的函數提到對象外:function basketball() {console.log('籃球');};// 構造函數:function Person(name, age, height, weight) {this.name = name;this.age = age;this.height = height;this.weight = weight;//對象中的方法使用構造函數內的函數:this.eat = function() {console.log('吃');};//對象中的方法調用構造函數外面的函數:this.play = basketball;};// 通過原型給構造函數添加方法: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,對象的原型指向構造函數console.log(person2.age == person1.age); //true,各個對象的屬性值相等的情況下這這兩個值相同console.log(person2.eat == person1.eat); //false,對象的方法的函數寫在構造函數中時,各個對象的指向不同console.log(person2.basketball == person1.basketball); //true,對象的方法的函數寫在構造函數外時,各個對象的指向相同console.log(person2.song == person1.song); //true,最終要通過原型的方式給對象添加相同的方法,實際開發中采用的方法</script>

簡單原型語法:

給原型添加屬性或者方法可以節省內存空間,共享數據,但是每次都要通過prototype的方式多次重復,為此可以將這些屬性或方法通過對象的形式寫在{}中,但是這種方法需要手動寫上構造器這個屬性,如:

<script>function Person(names, age) {this.names = names;this.age = age;};// 通過對象的方式給原型添加屬性和方法后,前面不能在以普通的方式添加屬性或方法,否則會報錯或undefined,添加在對象形式后面是可以的:Person.prototype = {constructor: Person, //手動添加構造器weight: 49,height: 180,eat: function() {console.log('面條')}};Person.prototype.colors = 'red'; //在對象形式的后面添加新的屬性或方法是沒事的Person.prototype.play = function() {console.log('籃球')}; //在對象形式的后面添加新的屬性或方法是沒事的var per = new Person('jack', 17);per.eat()console.log(per.weight);console.log(per.colors);per.play();</script>

原型中方法可以互相訪問:

原型中的方法可以互相訪問,方法中可以調用屬性;如果要訪問一個屬性或方法,首先會到實例對象中去找,若無才會去原型中找。若還是沒有則返回undefined

<script>function Person(names, age) {this.names = names;this.age = age;};Person.prototype = {constructor: Person, //手動添加構造器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>

內置對象原型中添加方法:

通過原型的方式可以給內置對象添加自定義方法:

<script>String.prototype.hello = function() {console.log('hello');};var str = new String();str.hello();//給數組添加求和方法: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.變量名 = 值;

原型鏈:

實例對象和原型直接的關系通過__proto__來聯系,這種關系稱為原型鏈。實例的指向可以通過proto進行改變。

通過原型繼承屬性或方法:

通過改變prototype的指向可以繼承父級的屬性或方法,如:

<script>function Person(names) {this.names = names;};Person.prototype.eat = function() {console.log('吃大米');};function Father(age) {this.age = age;};// 將Father構造函數中的原型指向new Person()實例對象中的原型Father.prototype = new Person('jack');Father.prototype.work = function() {console.log('工作');};function Myfather(weight) {this.weight = weight;};// 將Father構造函數中的原型指向new Person()實例對象中的原型Myfather.prototype = new Father(30);var myfather = new Myfather(50)console.log(myfather.names + '---' + myfather.age + '---' + myfather.weight);myfather.eat();myfather.work();</script>

通過call借用構造函數實現繼承:

通過改變原型的指向實現繼承存在一個缺陷:改變指向時,初始化了實例對象,屬性的值已經寫死,無法改變,為了解決這個缺陷,可以借用構造函數實現繼承,(call方法的使用:在需要繼承父級屬性的子級構造函數中通過:父級構造函數.call(改變函數this的指向,父級構造函數中的參數,子級構造函數中的參數)),子級構造函數中的形參寫上父級構造函數中的形參,但是這種方式只能繼承屬性,若要繼承方法,那么就要將借用構造函數和改變原型相結合,如:

<script>function Person(names, sex) {this.names = names;this.sex = sex;};Person.prototype.eat = function() {console.log('吃飯');};//借用構造函數實現屬性繼承:function Student(names, sex, score) {Person.call(this, names, sex, score);//第一個參數是改變Person中this的指向為Student構造函數實例對象this.score = score;};// 單獨的借用構造函數只能實現屬性繼承,方法不能繼承,因此實際開發中可以將借用構造函數和改變原型指向結合使用: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調用函數:

apply(參數1,數組形式參數2)和call相似,也可以調用函數并改變函數中this的指向,第一個參數改變函數中this的指向,第二個參數以數組的形式傳參數,返回的是字符串形式的值;但是apply的主要用法是調用內置對象方法來實現某些函數中沒有的方法的功能,如:

<script>// 實現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方法來實現求數組中最小值:var array = [2, 3, 4, 1]var minValue = Math.min.apply(null, array); //當一個形參不需要實參時可以用null代替,這里最好將指向指為apply的調用者console.log(minValue); //1console.log(Math.max(2, 3, 4, 1)); //4,Math對象中求最大值最小值的方法中傳入的是數字</script>

bind拷貝函數:

fn.bind(參數1,參數2),不會調用原函數,但是可以通過第一個參數改變函數this的指向并返回一個新函數;此方法不會立即執行函數,而call和apply都會立即執行行數,因此bind在實際開發中用的會比較多。

拷貝繼承:

淺拷貝:指的是地址的拷貝;深拷貝:指完全的把堆上的代碼也拷貝,但是地址不拷貝。

<script>var obj1 = {names: 'jack',age: 18};// 1.通過改變指針實現拷貝繼承:var obj2 = obj1;console.log(obj2.names);// 2.通過for-in遍歷將obj1的屬性和值存到obj3中:var obj3 = {};for (var key in obj1) {obj3[key] = obj1[key];};console.log(obj3.names);// 3.通過遍歷原型的屬性和方法拷貝對象: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>

構造函數、實例對象、原型之間的關系:

通過class來創建對象:

class類指的是一類具有相似屬性或方法的事物,通過new也可以創建實例對象,其語法是:class 類名{},class類的大括號中要寫構造器:constructor(形參){this.屬性或方法},但是實際開發中不建議將方法寫在構造器中,而是省去關鍵字function直接寫在class類中,之后通過new實例化對象,如:

<script>class Person {constructor(names, age) {this.names = names;this.age = age;// 方法不建議這樣寫:this.eat = function() {console.log('面條')};};// 類中的方法建議寫在類中:play() {console.log('籃球')};};var personOne = new Person('jack', 18);console.log('names:' + personOne.names + '---age:' + personOne.age);personOne.eat();personOne.play();</script>

class類的繼承:

class類可以繼承一個類的屬性和方法,其語法:class 新類名 extends 被繼承類名 {};之后通過new實例化對象即可,如:

<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()調用父級類中的構造器:

被繼承后的類,若要調用父級的方法,而方法中有參數,此時給子級實例對象傳入參數是無法被父級中的方法中拿到的,此時需要給子級構造器中通過super(參數)將子級實例對象中的參數傳給父級構造器,super還可以調用父類中的父類中的普通方法,如:

<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) {// 這里不能直接通過this來設置屬性接收參數,而要通過super()調用父級中的構造器,才能調用父級的方法:super(a, b);//必須在this接收參數之前調用super// this.a = a;//這里的this.參數 是給自己的方法準備的參數,自己的方法調用時需要接收的參數// this.b = b;}play() {super.play();console.log('排球');}; };var sonOne = new Son(1, 2);console.log(sonOne.sum());sonOne.play(); //方法的調用首先會先 從自己的類中找,若沒有則去父級類中找,若還是沒有會報錯,其中有則執行方法(就近原則)</script>

開啟嚴格模式:

嚴格模式在IE10以上版本才支持,消除了javascript中的一些問題寫法;若要給某個作用域開啟嚴格模式,則在該作用域寫入以下代碼即可:

'use strict';//用來開啟嚴格模式:嚴格模式指的是書寫代碼必須按照代碼規范,不能省略代碼

高階函數:

高階函數是對其他函數進行操作的函數,它接受的參數是函數或返回的是函數。

<script>function f1(callback) {callback && callback();};f1(function f2() {console.log('這是高階函數')});</script>

閉包:

閉包指:有權訪問另一函數作用域中變量的函數(在普通函數中是無法訪問到其他作用域的變量的),其作用是延伸了變量的作用范圍,

<script>function f() {var str = '123';function f2() {console.log(str);};return f2;};var result = f(); //這里的f接收的是f2函數,相當于在f外面打印str,高階函數實現閉包result();</script><script>// 利用閉包打印出li的類容:類似這種問題可以采用:for循環里面首先放入自執行函數,自執行函數里面寫入處理業務的代碼// 通過遍歷將循環里面的所有代碼存到內存中,等定時器啟動后,執行業務代碼,閉包也有壞處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>

遞歸:

遞歸指:一個函數在內部可以調用自己本身,那么這個函數就是自己,由于遞歸可能出現死循環發生棧溢出,所以必須要加退出條件return。

<script>var i = 0;function f() {console.log(i);if (i > 5) {return;};i++;f();};f();</script>

es6內容簡介:

關鍵字let、const:

let關鍵字是es6中聲明變量的,其作用和var相似,let聲明的變量只在塊級有效,塊級作用域指{}里面,沒有變量提升,必須先聲明后使用,具有暫時性死區性(使用一個變量先從本塊級作用域查找,有則使用,注意變量沒有提升,MDN文檔中有變量提升,但是會拋出錯誤)。

const關鍵字是es6中聲明常量的,因此若要改變這個關鍵字聲明的常量,就會報錯,它也是在塊級有效,變量不會提升,MDN文檔中有變量提升,但是會拋出錯誤。

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

解構賦值:

es6中允許從數組或對象中提取值,按照對應位置,對變量賦值;對象中每個屬性名和前面屬性名一致;若在對象中,前面也是鍵值對的形式,那么這值實際是變量,接收的是對應的后面對象張的值,如:

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

箭頭函數:

箭頭函數是es6中另一種寫法,其作用和普通函數一樣,只是在書寫上比較簡潔了。箭頭函數沒有函數名,因此通常用變量接收,如:const fn =()=>{};,小括號中可以傳入形參;箭頭函數中的this不指向調用者,而指函數定義位置的上下文中this即:箭頭函數所在作用域中的this

<script>var sum = (x, y) => {console.log(x + y);};sum(2, 3); //5// 當函數體中只有一句執行代碼,且這行代碼就是函數的返回值,此時可以省略{}:var sum1 = (x, y) => console.log(x + y);sum1(1, 2); //3// 當函數的形參只有一個的時候可以省略():const num = x => console.log(x);num(5); //5</script>

剩余參數:

當函數的實參大于一個形參的個數時,給形參最后一個參數見面加…后(當然可以給第一個形參直接加…,此時將傳入的實參以數組的形式返回),剩余的實參則會以數組的形式存在最后一個形參里面:

<script>function num(num1, num2, ...numn) {console.log(numn);};num(1, 2, 3, 4); //[3, 4]// 剩余參數和解構配合:var [num1, ...num] = [1, 2, 3, 4, 5];console.log(num); //[2, 3, 4, 5]</script>

擴展運算符:

擴展運算符可將數組或對象轉為用逗號分隔的參數序列,其語法是在變量名前面加…,如:

<script>var arr = [1, 2, 3];console.log(...arr); //1 2 3,原本...arr里面是用逗號隔開的,但是這里是因為console.log將里面的逗號當做分隔符了。//擴展運算符可以將多個數組合并: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]// 利用擴展運算符將偽數組轉換為真數組:其語法:[...偽數組變量名]</script>

模板字符串:

使用反引號的字符串稱之為模板字符串,可以很好地將變量解析到字符串中的語法,其語法:在反引號中使用(${變量名}),模板字符串支持換行,支持調用函數如:

<script>var num = 2;var str = `今天是${num}號`;console.log(str);// 調用函數和換行:var say = () => {return 'hello'};var sayhe = `${say()}word`;console.log(sayhe);</script>

Set數據結構:

Set數據結構類似數組,但是成員的值都是唯一的(當傳入的數據中有重復的值時,會自動將重復值去掉),其是一個構造函數,需要實例化對象才能使用:const sets = new Set();此對象可以接收一個數組,數組中的數據會被自動存到set數據結構中;支持forEach遍歷set數據:

<script>var sets = new Set([1, 2, 2]);console.log(sets.size); //2,size屬性用來獲取set中存的不重復值的個數,和length類似。// 給sets增加數據:add(value)sets.add(3);console.log(sets); //Set(3) {1, 2, 3}//刪除sets數據中的值:delete(value),并返回一個布爾值用于判斷是否刪除成功:var result = sets.delete(1);console.log(result); //trueconsole.log(sets); //Set(2) {2, 3}// 判斷某個值是否是sets中的成員:has(value),返回一個布爾值var results = sets.has(7);console.log(results); //false// 清空sets中的數據:clear():sets.clear();console.log(sets);//Set(0) {}</script>

數組查詢:find和findindex:
在es6中,js為數組提供了一個遍歷數組查詢某項的API:find-----需要傳入一個函數作為參數;同樣在es6中js為數組提供了一個遍歷數組查詢某項下標的API:findIndex—也需要傳入一個函數作為參數,如下案例:

var arr = [{'id':1,'name':'一'},{'id':2,'name':'二'},{'id':3,'name':'三'},{'id':4,'name':'四'} ]; // 當函數中的條件滿足時,會終止遍歷并返回這個條件的數組項 var result = arr.find(function(item){return item.id === 3; }); console.log(result);// 當函數中的條件滿足時,會終止遍歷并返回滿足條件的這項下標 var resultElse = arr.findIndex(function(item){return item.id === 4; }); console.log(resultElse)// 原理: Array.prototype.myFind = function (conditionFunc) {// var conditionFunc = function (item, index) { return item.id === 4 }for (var i = 0; i < this.length; i++) {if (conditionFunc(this[i], i)) {return this[i]}} }var ret = users.myFind(function (item, index) {return item.id === 2 })console.log(ret)

提示:本文圖片等素材來源于網絡,若有侵權,請發郵件至郵箱:810665436@qq.com聯系筆者 刪除。
筆者:苦海

總結

以上是生活随笔為你收集整理的javascript中实例对象和构造函数关系、原型语法、原型链、call实现继承、apply调用函数、bind拷贝函数、拷贝继承、class类、super、严格模式、高阶函数、闭包、递归、es6简介的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。