構造函數、原型、繼承原來這么簡單?來吧,深入淺出

構造函數

小編上篇博客中介紹到的通過關鍵字class方式定義類,然后根據類再創建對象的方式,是ES6中語法,現在很多瀏覽器對ES6的支持還不是很好,所以也要學習通過構造函數(構建函數)的方式創建對象

問?既然瀏覽器對ES6的支持不是很好,是不是編寫代碼時不要使用ES6語法呢?(看完這篇文章你就有答案了)

1.構造函數和原型

1.1對象的三種創建方式–復習

  1. 字面量方式

    var obj = {};
    
  2. new關鍵字

    var obj = new Object();
    
  3. 構造函數方式

    function Person(name,age){this.name = name;this.age = age;
    }
    var obj = new Person('zs',12);
    

說明:

構造函數是一種特殊的函數,主要用來初始化對象,即為對象成員的值進行初始化,其與new一起使用用于創建對象

這里所說的構造函數與前面講的類中的構造函數不太一樣,類中的構造函數主要是給類中的屬性賦值,這里的構造函數中,既可以包屬性,也可以包含方法,與上面所說的類的概念更接近,可以看成是J S 徹底向面向對象轉變過程中的一種過度,四不像

所以在編寫構造函數時,可以參考類的定義方式,將對象的一些公共的屬性和方法抽象出來,然后封裝到這個函數中

如下面分別使用ES6中的class和ES5中的構造函數的方式生成實例對象

		/**ES6 中創建對象的方法:先使用class關鍵字創建類,然后使用 new 類名() 的方式創建類的對象*/class Person {constructor(name, age) {this.name = namethis.age = age}speak(){console.log('哇哇哇哇哇哇哇')}}// 創建類的對象var p1 = new Person('李白', 20)// 訪問類中的屬性console.log(p1.name)p1.speak()console.log('---------------------')/**ES5 中創建對象的方法:先創建構造函數,然后使用 new 函數名稱() 的方式創建這個函數的對象*/function Star(name, gender) {this.name = namethis.gender = genderthis.sing=function(){console.log('小呀嘛小二郎')}}// 通過構造函數創建對象var s1 = new Star('杜甫', '男')console.log(s1.gender)s1.sing()

圖解

在這里插入圖片描述

注意兩點

1)構造函數首字母大寫,就給使用class創建類一樣

2)與new關鍵字一起使用,這更與class一樣

3)最為重要的一點是:類的編寫方法更像是語法糖,目的是讓我們能夠快速、舒服、優雅的編寫類,但是從本質上來說,類其實就是函數。初學者可能感覺不到 class 方式定義類相較于 構造函數的優勢:1)沒有體會到通過構造函數的方式實現繼承的痛苦,所以無法理解通過 ES6 中 extends 實現繼承的優勢; 2)沒有見識過傳統的面向變成語言

console.log(typeof Person);
console.log(typeof FPerson);

結果

在這里插入圖片描述

new的解釋

在內存中創建一個新的空對象

讓this指向這個對象,所以在代碼中使用this,就是使用這個對象,this 跟類沒有關系

執行構造函數中的代碼,給這個對象添加屬性和方法,但是方法中的代碼不會執行

1.2靜態成員和實例成員

1.2.1實例成員

實例成員就是構造函數內部通過this添加的成員 如下列代碼中 name age sing 就是實例成員,實例成員只能通過實例化的對象來訪問

  /*通過this添加的成員就是實例成員1)實例成員只能通過對象.成員的方式訪問2)實例成員與每個對象相關,也就是每個對象的成員的值是不一樣的*/function Star(name, gender) {this.name = namethis.gender = genderthis.sing = function () {console.log('小呀嘛小二郎')}}// 通過構造函數創建對象var s1 = new Star('杜甫', '男')var s2 = new Star('蔡徐坤', '女')console.log(s1.gender)console.log(s2.gender)// 實例成員不能通過 【構造函數名稱.成員】 的方式訪問// console.log(Star.gender) // undefined

這點與ES6中 class 創建的類是一樣的

class Star {constructor(uname, age) {this.uname = unamethis.age = age}sing() {console.log('我會唱歌')}
}var ldh=new Star('劉德華',17)
console.log(ldh.uname)

1.2.2靜態成員

靜態成員 在構造函數本身上添加的成員 如下列代碼中 就是靜態成員,靜態成員只能通過構造函數來訪問

在這里插入圖片描述

這與通過 class 關鍵字定義類時一樣的

總結:

實例成員屬于對象,所以兩個對象的實例成員的值不一樣

靜態成員,屬于構造函數本身,每個對象都屬于這個構造函數,所以多個對象共享一個靜態成員

?

1.3構造函數的問題

構造函數方法很好用,但是存在浪費內存的問題。

在這里插入圖片描述

1.4構造函數原型prototype

構造函數通過原型分配的函數是所有對象所共享的。

JavaScript 規定,每一個構造函數都有一個prototype 屬性,指向另一個對象。注意這個prototype就是一個對象,叫做原型對象

ES6 中的類也是一樣,因為我們說過,類從本質上來講,也是一個函數

        function Star(name, gender) {this.name = namethis.gender = genderthis.sing = function () {console.log('小呀嘛小二郎')}}console.log(Star.prototype)

在這里插入圖片描述

這個對象的所有屬性和方法,都會被構造函數所擁有

function Star(name, gender) {this.name = namethis.gender = genderthis.sing = function () {console.log('小呀嘛小二郎')}}// 為Star的原型對象添加方法(相當于將方法添加到Star的父類上去)Star.prototype.cry=function(){console.log('我要cry,cry,cry,cry,cry')}Star.prototype.dance=function(){console.log('一步一步,似魔鬼的步伐')}// 通過輸出發現,原型對象上確實有了 cry 方法console.log(Star.prototype)// 那么作為原型對象的子類的 Star 構造函數自然就擁有了cry 方法var s1 = new Star('杜甫', '男')s1.cry()s1.dance()var s2 = new Star('蔡徐坤', '女')s2.cry()s2.dance()

還可以使用對象的方式為原型添加多個方法

我們可以把那些不變的方法,直接定義在 prototype 對象上,這樣所有對象的實例就可以共享這些方法。

解惑:

1)這個原型,就類似于其他語言中的基類。。。。

2)不僅使我們自己使用構造函數或類定義的對象,JS中的內置對象的方法,其實都定義在這個對象的原型對象上

var arr=[]
// 查看對象的原型對象使用 __proto__ 屬性
console.log(arr.__proto__)
// 查看構造函數或類的原型對象使用 prototype 屬性
console.log(Array.prototype)
// 總結:對象的__proto__ 屬性和 類或者構造函數的 protptype 屬性指向的是同一個對象

1.5對象原型

構造函數的prototype 屬性獲取的是當前構造函數的原型對象
構造函數的實例的__proto__屬性獲取的是當前對象的對象原型
這兩者是一個對象,也就是說構造函數的原型對象與此構造函數的實例的對象原型是一個對象

在這里插入圖片描述

在這里插入圖片描述

 function Star(name, gender) {this.name = namethis.gender = genderthis.sing = function () {console.log('小呀嘛小二郎')}}// 為Star的原型對象添加方法(相當于將方法添加到Star的父類上去)Star.prototype.cry = function () {console.log('我要cry,cry,cry,cry,cry')}Star.prototype.dance = function () {console.log('一步一步,似魔鬼的步伐')}// 通過輸出發現,原型對象上確實有了 cry 方法console.log(Star.prototype)// 那么作為原型對象的子類的 Star 構造函數自然就擁有了cry 方法var s1 = new Star('杜甫', '男')// s1.cry()// s1對象的 __proto__屬性獲取是的是s1對象的對象原型console.log(s1.__proto__)// 驗證構造函數的原型對象與實力的對象原型是一個對象console.log(Star.prototype===s1.__proto__)

1.6constructor構造函數

對象原型( proto)和構造函數(prototype)原型對象里面都有一個屬性 constructor 屬性(因為兩個其實是一個東西) ,constructor 我們稱為構造函數,因為它指回構造函數本身。

下面通過代碼理解

        function Star(name, gender) {this.name = namethis.gender = genderthis.sing = function () {console.log('小呀嘛小二郎')}}      var s1 = new Star('杜甫', '男')// 輸出構造函數的原型對象console.log(Star.prototype)// 輸出對象的對象原型console.log(s1.__proto__)

在這里插入圖片描述

通過上面的代碼,我們看到,constructor 屬性的值確實是這個對象對應的構造函數

不僅可以通過這個屬性,獲取原型對象所屬的構造函數,constructor屬性 還可以讓原型對象重新指向原來的構造函數

一般情況下,對象的方法都在構造函數的原型對象中設置。

如下面這樣

// 為構造方法的原型對象中添加speak 方法
Person.prototype.speak=function(){console.log('人類說話')
}

但是如果加入多個方法,使用上面的方式就比較麻煩

function Star(name, gender) {this.name = namethis.gender = gender
}
// 像原型添加sing方法
Star.prototype.sing = function () {console.log('紅星閃閃放光彩');
}
// 向原型添加 dance 方法
Star.prototype.dance = function () {console.lo('魔鬼的步伐')
}
// 向原型添加fly
Star.prototype.fly = function () {console.log('上了飛機就拖鞋')
}

像上面這樣,如果要添加多個方法,我們可以給原型對象采取對象形式賦值,如下面的代碼

Star.prototype = {sing: function () {console.log('紅星閃閃放光彩');},dance: function () {console.lo('魔鬼的步伐')},fly: function () {console.log('上了飛機就拖鞋')}
}

但是這樣就會覆蓋構造函數原型對象原來的內容,這樣修改后的原型對象 constructor 就不再指向當前構造函數了

此時,我們可以在修改后的原型對象中,添加一個 constructor 指向原來的構造函數。

在這里插入圖片描述

結果

在這里插入圖片描述

總結:如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用constructor指回原來的構造函數如:

完整代碼

function Star(name, gender) {this.name = namethis.gender = gender
}        
Star.prototype = {construcotr:Star,sing: function () {console.log('紅星閃閃放光彩');},dance: function () {console.lo('魔鬼的步伐')},fly: function () {console.log('上了飛機就拖鞋')}
}
console.log(Star.prototype)

1.7原型鏈

? 每一個實例對象又有一個__proto__屬性,指向的構造函數的原型對象,構造函數的原型對象也是一個對象,也有__proto__屬性,這樣一層一層往上找就形成了原型鏈。

可以類比基類,基類就是Object

其實所有的自定義的或者系統內置的構造函數或者類的最頂級的對象原型都是 Object

在這里插入圖片描述

1.8構造函數實例和原型對象三角關系

1.構造函數的prototype屬性指向了構造函數原型對象,構造函數的原型對象的constructor屬性指向了構造函數

function Star(name, age) {this.name = namethis.age = age
}
// 獲取輸出構造方法的原型對象
console.log(Star.prototype)
// 獲取并輸出原型對象的構造函數
console.log(Star.prototype.constructor)
// 證明原型對象的constructor屬性確實獲取的是對應的構造函數
console.log(Star.prototype.constructor===Star)

2.實例對象是由構造函數創建的,實例對象的__proto__屬性指向了構造函數的原型對象

// 實例對象由構造函數創建
var s1=new Star('肖戰',18)
// 實例對象的__proto__屬性指向了對應構造函數的原型對象
console.log(s1.__proto__)

3.構造函數的原型對象的constructor屬性指向了構造函數,實例對象的原型就是構造函數的原型對象,此對象中有constructor屬性也指向了構造函數

在這里插入圖片描述

重要說明:上面所說的理論同樣適用于ES6中

class Star {constructor(name){this.name=name}
}
var s=new Star('yhb')
console.log(Star.prototype)
console.log(s.__proto__)

1.9原型鏈和成員的查找機制

任何對象都有原型對象,也就是prototype屬性,任何原型對象也是一個對象,該對象就有__proto__屬性,這樣一層一層往上找,就形成了一條鏈,我們稱此為原型鏈;

當訪問一個對象的屬性(包括方法)時,首先查找這個對象自身有沒有該屬性。
如果沒有就查找它的原型(也就是 __proto__指向的 prototype 原型對象)。
如果還沒有就查找原型對象的原型(Object的原型對象)。
依此類推一直找到 Object 為止(null)。
__proto__對象原型的意義就在于為對象成員查找機制提供一個方向,或者說一條路線。

1.10原型對象中this指向

構造函數中的this和原型對象的this,都指向我們new出來的實例對象

1、構造函數中的this指向的就是new出來的對象

function Star(name, age) {this.name = namethis.age = ageconsole.log(this)
}
var s1=new Star('李白',20)
var s2=new Star('杜甫',17)

在這里插入圖片描述

2、構造函數的原型對象上的this指向的也是new出來的對象

function Star(name, age) {this.name = namethis.age = ageconsole.log(this)
}
Star.prototype.sing=function(){console.log(this)
}
var s1=new Star('李白',20)
var s1=new Star('杜甫',17)

在這里插入圖片描述

通過下面的代碼也可以比較兩個到底是不是都只想了 new 出來對象

 function Star(name, age) {this.name = namethis.age = age            }var that = null// 構造函數的原型對象中的thisStar.prototype.sing = function () {that = this}var s1 = new Star('李白', 20)// 韓炳旭說:sing方法一定要調用,否則無法執行賦值操作s1.sing()console.log(that === s1)

1.11通過原型為數組擴展內置方法

查看數組的原型

 console.log(Array.prototype);

為數組擴展和一個方法,可以計算數組中元素的和

 var numbers = new Array(1, 2, 3, 4, 5)// 傳統方法求和// var sum = 0// for (var i = 0; i < numbers.length; i++) {//     sum += numbers[i]// }// 通過改變原型Array.prototype.sum = function () {var sum = 0for (var i = 0; i < this.length; i++) {sum += this[i]}return sum}console.log(numbers.sum())// 再創建一個數組,使用[]方式創建的也是Array類的實例var arr=[2,3,4,7]console.log(arr.sum())console.log(Array.prototype)

2.繼承

在ES6之前,沒有extends 關鍵字實現類的繼承,需要通過構造函數+原型對象的方式模擬實現繼承,這種方式叫做組合繼承

2.1call()

  • call()可以調用函數
  • call()可以修改this的指向,使用call()的時候 參數一是修改后的this指向,參數2,參數3(普通參數)…使用逗號隔開連接

下面代碼單純的調用函數

function f1() {console.log(this) //window
}
f1.call()

下面代碼修改this的指向

  function f1() {/**1)默認情況下,this=window*2)使用call修改后,this=p*/console.log(this) }f1.call() // 輸出window// 創建對象pvar p={}// 將函數f1的this指向修改為對象pf1.call(p) // 輸出p

上面call 方法的第一個參數就是this引用的新對象,后面的參數作為函數 f1 的普通參數

代碼演示

2.2子構造函數繼承父構造函數中的屬性

下面利用上面講到的知識實現構造函數的繼承(所謂繼承,就是讓一個類擁有另一個類中的屬性和方法,換言之,就是將A類中的屬性和方法的宿主換成B的對象)

步驟如下

  1. 先定義一個父構造函數
  2. 再定義一個子構造函數
  3. 子構造函數繼承父構造函數的屬性(使用call方法)

在這里插入圖片描述

通過調試證明上面的結論

上面的案例只演示了屬性的繼承,方法的繼承是一樣的

在這里插入圖片描述

2.3借用原型對象繼承方法

上面的方式,可以繼承構造函數(為了簡單,以后我們稱其為類)中的方法,但前面講過,實際開發中,我們更喜歡將方法注冊到類的原型上

function Father(name, age) {this.name = namethis.age = age}Father.prototype.speak = function () {console.log('hello')}function Son(gender) {// 注釋 ①Father.call(this, '張三', 20)this.gender = gender}var f=new Father('yhb',30)console.log(f)        var s = new Son('女')console.log(s)

輸出結果

在這里插入圖片描述

所以,Son 的對象中就沒有 speak 方法

其實原因很簡單,在Father的原型對象上添加了speak方法,那么Father會繼承這個方法,但當前 Son與Father以及Father的原型并沒有任何關系,我們只不過通過 call 方法巧妙的使用了其 name和age 屬性而已,所以Son中自然沒有speak 方法

如何解決呢?

我們可以修改Son的原型為Father的原型,這樣的話Son就擁有了speak 方法

在這里插入圖片描述

輸出結果

在這里插入圖片描述

我們發現,Son中確實擁有了speak 方法

但是問題也隨之出現,因為 Father 與 Son 此時的原型對象是一個,所以此時我們如果想 Son的原型對象上添加一個方法

 Son.prototype.run=function(){console.log('run')}

再分別輸出兩個對象

在這里插入圖片描述

這就違反了繼承的原則:只能兒子繼承父親的,但現在是父親也能繼承兒子的

解決方案:將下面的代碼

Son.prototype=Father.prototype

替換成下面這個

 Son.prototype=new Father()

也就是讓Son的原型對象指向 Father 的對象實例,這個實例的 proto 屬性指向Father的對象原型,所以其中具有speak方法,但這僅僅是一個實例對象,就想從Father類拷貝了一份,修改此對象的原型,不會影響ather類的對象,所以修改此實例,不會影響到Father 的原型對象

稍微有點小問題就是,此時 Son的構造函數指向的是Father的構造函數了

console.log(s.constructor)

在這里插入圖片描述

使用下面的代碼再將其構造函數指回Son的構造函數

 Son.prototype.constructor=Son

在這里插入圖片描述

完整代碼

 /* 利用call 實現構造函數的繼承*/function Father(name, age) {this.name = namethis.age = age}Father.prototype.speak = function () {console.log('hello')}function Son(gender) {// 注釋 ①Father.call(this, '張三', 20)this.gender = gender}Son.prototype=new Father()// 修改Son的構造函數為SonSon.prototype.constructor=Son// 像Son的原型對象中添加一個方法Son.prototype.run=function(){console.log('run')}//var f=new Father('yhb',30)// console.log(f)        var s = new Son('女')console.log(s)console.log(s.constructor)

圖解:

3.ES5新增方法

關于 ECMAScript 與 JS 的關系,以及 ES 各個版本,大家可以自行百度,小編在這里不做展開說明

ES6 是在ES5的基礎上升級,所以先學習ES5新增的特性,后面再學習ES6新增的特性

3.1數組方法forEach遍歷數組

此方法用來便利數組,參數為一個函數

以后再想便利數組就不用自己編寫循環了

var numbers = [1, 3, 5, 7, 9]
numbers.forEach(function (item, index, ary) {console.log('元素:' + item);console.log('索引:' + index);console.log('數組本身:' + ary);
})

案例:數組求和

var sum=0
numbers.forEach(function(item){sum+=item
})
console.log(sum)

3.2數組方法filter過濾數組

此方法有一個返回值,用于接收所有符合過濾條件的元素,返回值的類型為數組

var numbers = [1, 2, 3, 4, 5, 6]
/*下面代碼從數組numbers中篩選出所有>4的元素,然后放到新數組result中注意:一定要有return 關鍵字*/
var result = numbers.filter(function (item, index) {return item > 4
})
console.log(result);

輸出結果

在這里插入圖片描述

3.3數組方法some


some 查找數組中是否有滿足條件的元素 var arr = [10, 30, 4];var flag = arr.some(function(item,index,array) {//參數一是:數組元素//參數二是:數組元素的索引//參數三是:當前的數組return item < 3;});
console.log(flag);//false返回值是布爾值,只要查找到滿足條件的一個元素就立馬終止循環

**some()** 方法測試數組中是不是至少有1個元素通過了被提供的函數測試。它返回的是一個Boolean類型的值。

如果用一個空數組進行測試,在任何情況下它返回的都是false

語法:

arr.some(callback(element[, index[, array]])[, thisArg])

1)返回值為布爾值

2)找到滿足條件的元素,就終止循環,不會繼續向后查找

可以利用這個函數查詢數組中是否存在某個值

 var numbers = [1, 2, 3, 4, 5, 6]function checkAvailability(arr, val) {var res = arr.some(function (element, index) {return element == val})return res}console.log(checkAvailability(numbers, 1))

3.4找水果案例

首先將數據定義在數組中,然后便利數組中的數據渲染到表格中,然后可以根據價格或者名稱查詢想吃的水果

  1. 定義數組對象數據

    var fruits = [{id: 001,title: '蘋果',price: 5},{id: 001,title: '蘋果',price: 5},{id: 002,title: '梨',price: 3},{id: 003,title: '香蕉',price: 6},{id: 004,title: '砂糖橘',price: 2}
    ]
    
  2. 使用forEach遍歷數據并渲染到頁面中

      var tbody = document.querySelector('tbody')fruits.forEach(function (item) {var tr = ` <tr><td>${item.id}</td><td>${item.title}</td><td>${item.price}</td></tr>`tbody.insertAdjacentHTML('beforeend',tr)})
    
  3. 根據價格篩選數據

    將篩選出的數據重新渲染到表中

    function setData(ary) {// 先刪除以前的數據tbody.innerHTML = ''ary.forEach(function (item) {var tr = ` <tr><td>${item.id}</td><td>${item.title}</td><td>${item.price}</td></tr>`tbody.insertAdjacentHTML('beforeend', tr)})}// 根據價格過濾商品var btnPrice = document.querySelector('#btnPrice')var min_price = document.querySelector('#min_price')var max_price = document.querySelector('#max_price')btnPrice.addEventListener('click', function () {var result = fruits.filter(function (item) {return item.price >= min_price.value && item.price <= max_price.value})// 重新渲染數據setData(result)})
    
    1. 根據名稱搜索數據
   // 根據名稱搜索var btnTitle = document.querySelector('#btnTitle')var title = document.querySelector('#title')btnTitle.addEventListener('click', function () {var result = fruits.filter(function (item) {return item.title == title.value
})// 重新渲染表格setData(result)})

上面數組中,水果名稱是唯一的

使用filter會便利每一個對象,然后比較,查詢效率相對較低

find 方法只要查詢到一個符合條件的就會停止,所以效率相對較高

 btnTitle.addEventListener('click', function () {// find 方法返回的不是數組,而是對象,所以要使用foreach,需要將// 返回的對象放到數組中var result = fruits.find(function (item) {console.log(item)return item.title == title.value})var arr = []arr.push(result)// 重新渲染表格setData(arr)})

完整代碼

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;}.box {width: 1000px;margin: 50px auto;}table,th,td {border: 1px solid #ccc;}table {width: 800px;border-collapse: collapse;text-align: center;margin-top: 20px;}th,td {padding: 5px 10px;}</style>
</head><body><div class="box"><label for="">價格</label><input type="text" id="min_price"><span>-</span><input type="text" id="max_price"><button id="btnPrice">搜索</button><label for="">名稱</label><input type="text" id="title"><button id="btnTitle">搜索</button><table><thead><tr><th>編號</th><th>名稱</th><th>價格</th></tr></thead><tbody></tbody></table></div><script>var fruits = [{id: 001,title: '蘋果',price: 5},{id: 002,title: '桃子',price: 10},{id: 003,title: '梨',price: 3},{id: 004,title: '香蕉',price: 6},{id: 005,title: '砂糖橘',price: 2}]// 獲取tbodyvar tbody = document.querySelector('tbody')setData(fruits)// 將數組中的數據渲染到表格中function setData(ary) {// 先刪除以前的數據tbody.innerHTML = ''ary.forEach(function (item) {var tr = ` <tr><td>${item.id}</td><td>${item.title}</td><td>${item.price}</td></tr>`tbody.insertAdjacentHTML('beforeend', tr)})}// 根據價格過濾商品var btnPrice = document.querySelector('#btnPrice')var min_price = document.querySelector('#min_price')var max_price = document.querySelector('#max_price')btnPrice.addEventListener('click', function () {var result = fruits.filter(function (item) {return item.price >= min_price.value && item.price <= max_price.value})// 重新渲染數據setData(result)})// 根據名稱搜索var btnTitle = document.querySelector('#btnTitle')var title = document.querySelector('#title')btnTitle.addEventListener('click', function () {// find 方法返回的不是數組,而是對象,所以要使用foreach,需要將// 返回的對象放到數組中var result = fruits.find(function (item) {console.log(item)return item.title == title.value})var arr = []arr.push(result)// 重新渲染表格setData(arr)})</script>
</body></html>

3.5some和forEach區別

  • 如果查詢數組中唯一的元素, 用some方法更合適,在some 里面 遇到 return true 就是終止遍歷 迭代效率更高
  • 在forEach和filter 里面 return 不會終止迭代

3.6 trim方法去除字符串兩端的空格

var str = '   hello   '
console.log(str.trim()//hello 去除兩端空格
var str1 = '   he l l o   '
console.log(str.trim()//he l l o  去除兩端空格

3.7獲取對象的屬性名

Object.keys(對象) 獲取到當前對象中的屬性名 ,返回值是一個數組

 var obj = {id: 1,pname: '小米',price: 1999,num: 2000
};
var result = Object.keys(obj)
console.log(result)//[id,pname,price,num]

3.8Object.defineProperty

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperty設置或修改對象中的屬性

Object.defineProperty(對象,修改或新增的屬性名,{value:修改或新增的屬性的值,writable:true/false,//如果值為false 不允許修改這個屬性值enumerable: false,//enumerable 如果值為false 則不允許遍歷configurable: false  //configurable 如果為false 則不允許刪除這個屬性 屬性是否可以被刪除或是否可以再次修改特性
})	

利用上面的方法,我們可以在不為文本框添加事件的同時,將文本框的值與對象中的某個屬性關聯起來

var username=document.querySelector('#username')
var data = {}
Object.defineProperty(data, "title", {get: function () {return username.value},set: function (newValue) {username.value=newValue},enumerable: true,configurable: true
})

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/248617.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/248617.shtml
英文地址,請注明出處:http://en.pswp.cn/news/248617.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[網絡流24題] 航空路線問題 (費用流)

洛谷傳送門 LOJ傳送門 這道題的圖還挺好想的吧 反正都是無向邊&#xff0c;起點走到終點再回到起點&#xff0c;就相當于從起點走$2$次到達終點&#xff0c;且這兩次不經過相同的點&#xff0c;還要經過盡可能多的點 很經典的費用流建圖 限制點通過次數->拆點連邊&#xff0…

Go語言字符串和正則表達式

字符串相關方法 獲取字符串長度 注意: Go語言編碼方式是UTF-8,在UTF-8中一個漢字占3個字節package main import "fmt" func main() { str1 : "lnj" fmt.Println(len(str1)) // 3 str2 : "lnj" fmt.Println(len(str2)) // 12 } 如果字符串中包含中…

你疏漏的 JS 函數硬核知識?這里幫你總結了

重點 更多前端知識 誠邀各位前端從事者愛好者加入前端大佬技術交流社區&#xff0c;本社區主要分享技術棧、個人心得、技術交流、問題解惑等前端體系交流 點擊下方文字加入 前端大佬技術交流社區 1. 函數的定義和調用 1.1 函數的定義方式 方式1 函數聲明方式 function 關鍵…

7 月 1 日

7 月 1 日 今日內容 1.計算機基礎知識 2.python簡介 3.快速入門 昨日回顧 無內容詳細 1.計算機基礎知識 輸入輸出設備 CPU 硬盤 電源 中央處理器 處理各種數據 相當于人的大腦 內存 存儲數據 硬盤 存儲數據的 什么是操作系統 控制計算機工作的流程 軟件 什么是應用程序 安裝在操…

再見了 React、Angular,Vue3 才是 yyds

切記一定要看到最后&#xff01;&#xff01;&#xff01; 最近看到一篇文章上面是一作者資訊一位IT前輩&#xff0c;問他怎么看待工作 2 年的前端開發&#xff0c;月薪就高達 30k、40k 的現狀。 他說&#xff0c;在眾多編程技術中&#xff0c;前端算比較容易入門和提升的&am…

HBase實戰:記一次Safepoint導致長時間STW的踩坑之旅

本文記錄了HBase中Safepoint導致長時間STW此問題的解決思路及辦法。上篇文章回顧&#xff1a;HBase Replication詳解?過 程 記 錄現象&#xff1a;小米有一個比較大的公共離線HBase集群&#xff0c;用戶很多&#xff0c;每天有大量的MapReduce或Spark離線分析任務在進行訪問&a…

scrapy 第一個案例(爬取騰訊招聘職位信息)

import scrapy import jsonclass TzcSpider(scrapy.Spider):# spider的名字&#xff0c;唯一name tzc# 起始地址start_urls [https://hr.tencent.com/position.php?keywordspython&tid0&lid2268]# 每個url爬取之后會調用這個方法def parse(self, response):tr resp…

系統帶你學習 WebAPIs 第一講

Web APIs 本篇學習目標&#xff1a; 能夠通過ID來獲取元素 能夠通過標簽名來獲取元素 能夠通過class來獲取元素 能夠通過選擇器來獲取元素 能夠獲取body和html元素 能夠給元素注冊事件 能夠修改元素的內容 能夠區分innerText和innerHTML的區別 能夠修改像div這類普通元素的屬性…

react-webpack config webpack@3.4.1

1.最重要的一點 yarn add webpack3.4.1 -g 2. 解決跨域請求 webpack.json 中添加 https://segmentfault.com/q/1010000008190876?_ea1579884 webpack config less -----框架 ----查看考鏈接 https://blog.csdn.net/mjzhang1993/article/details/79013430轉載于:https://w…

系統帶你學習 WebAPIs 第二講

Web APIs 本篇學習目標&#xff1a; 能夠說出排他操作的一般實現步驟 能夠使用html5中的dataset方式操作自定義屬性 能夠根據提示完成百度換膚的案例 能夠根據提示完成全選案例 能夠根據提示完成tab欄切換案例 能夠區分元素節點、文本節點、屬性節點 能夠獲取指定元素的父元素 …

在微信瀏覽器中 location.reload() 不刷新解決方案(直接調用方法)

1、問題 在微信瀏覽器中&#xff0c;需要時刷新當前頁面。 正常情況下我們直接使用 location.reload 方法來刷新。 2、解決方法 function realod(){var {search,href} window.location;href href.replace(/&?t_reload(\d)/g,)window.location.href href(search?&:…

Python爬蟲學習筆記1:request、selenium、ChromeDrive、GeckoDriver等相關依賴安裝

系列學習筆記參考&#xff1a;python3網絡爬蟲開發實戰 requests # pip install requests import requestsselenium Selenium是一個自動化測試工具&#xff0c;利用它我們可以驅動瀏覽器執行特定的動作&#xff0c;如點擊、下拉等 操作 。 對于一些 JavaScript誼染的頁面來說&a…

系統帶你學習 WebAPIs 第三講

Web APIs 本篇學習目標&#xff1a; 能夠使用removeChild()方法刪除節點 能夠完成動態生成表格案例 能夠使用傳統方式和監聽方式給元素注冊事件 能夠說出事件流執行的三個階段 能夠在事件處理函數中獲取事件對象 能夠使用事件對象取消默認行為 能夠使用事件對象阻止事件冒泡 能…

CSS3文本與字體

一、CSS3 換行 1、word-break&#xff08;規定自動換行的處理方法&#xff09; word-break: normal / break-all / keep-all;/* normal&#xff1a;使用瀏覽器默認的換行規則 break-all&#xff1a;允許在單詞內換行 keep-all&#xff1a;只能在半角空格或連字符處換行 */ 兼容…

系統帶你學習 WebAPIs 第四講

Web APIs 本篇學習目標&#xff1a; 能夠說出常用的3-5個鍵盤事件 能夠知道如何獲取當前鍵盤按下的是哪個鍵 能夠知道瀏覽器的頂級對象window 能夠使用window.onload事件 能夠使用window.onresize事件 能夠說出兩種定時器的區別 能夠使用location對象的href屬性完成頁面之間的跳…

linux chrome 安裝過程記錄

最近&#xff0c;由于公司需要做爬蟲抓取一些新聞&#xff0c;在開發過程中&#xff0c;發現有些網站有一定的反爬措施&#xff0c;通過瀏覽器訪問一切正常&#xff0c;通過其他方式&#xff0c;包括&#xff1a;curl&#xff0c;urlconnection 等&#xff0c;就算加入了cookie…

系統帶你學習 WebAPIs 第五講

Web APIs 本篇學習目標: 能夠說出常見 offset 系列屬性的作用 能夠說出常見 client 系列屬性的作用 能夠說出常見 scroll 系列屬性的作用 能夠封裝簡單動畫函數 **1.1. **元素偏移量 offset 系列 1.1.1 offset 概述 offset 翻譯過來就是偏移量&#xff0c; 我們使用 offset系…

ajax請求相關問題

Ajax中async:false/true的作用&#xff1a; async. 默認是 true&#xff0c;即為異步方式&#xff0c;$.ajax執行后&#xff0c;會繼續執行ajax后面的腳本&#xff0c;直到服務器端返回數據后&#xff0c;觸發$.ajax里的success方法&#xff0c;這時候執行的是兩個線程。 async…

有贊美業微前端的落地總結

2020年4月&#xff0c;有贊美業的前端團隊歷經7個月時間&#xff0c;完成了美業PC架構從單體SPA到微前端架構的設計、遷移工作。PPT在去年6月份就有了&#xff0c;現在再整理一下形成文章分享給大家。 頭圖 目錄 Part 01 “大話”微前端 微前端是什么 背景 目標 達成價值 …

bcp文件, 逗號文件

bcp 實用工具 https://docs.microsoft.com/zh-cn/sql/tools/bcp-utility?viewsql-server-2017 大容量復制程序實用工具 (bcp) 可以在 Microsoft SQL Server 實例和用戶指定格式的數據文件間大容量復制數據。 使用 bcp 實用工具可以將大量新行導入 SQL Server 表&#xff0c;或…