JavaScript關(guān)于prototype實例詳解(超重點)
JavaScript關(guān)于prototype(超重點)
prototype是js里面給類增加功能擴展的一種模式.寫個面向?qū)ο髞砜纯?
function People(name, age){ this.name = name; this.age = age; this.run = function(){ console.log(this.name+"在跑") } } p1 = new People("張三", 18); p2 = new People("李四", 19); p1.run(); p2.run();
我現(xiàn)在代碼寫完了. 突然之間, 我感覺好像少了個功能. 人不應(yīng)該就一個功能. 光會跑是不夠的. 還得能夠ooxx. 怎么辦? 直接改代碼? 可以. 但不夠好. 如果這個類不是我寫的呢? 隨便改別人代碼是很不禮貌的. 也很容易出錯. 怎么辦? 我們可以在我們自己代碼中對某個類型動態(tài)增加功能. 此時就用到了prototype.
function People(name, age){ this.name = name; this.age = age; this.run = function(){ console.log(this.name+"在跑") } } // 通過prototype可以給People增加功能 People.prototype.xxoo = function(){ console.log(this.name+"還可以xxoo"); } p1 = new People("張三", 18); p2 = new People("李四", 19); p1.run(); p2.run(); p1.xxoo(); p2.xxoo();
能看到一些效果了是吧. 也就是說. 可以通過prototype給我們的對象增加一些功能.
接下來. 聊幾個重要的概念.
1.構(gòu)造器
構(gòu)造一個對象的函數(shù). 叫構(gòu)造器.
function People(){ //這個東西就是構(gòu)造器 constractor } var p = new People(); // 調(diào)用構(gòu)造器 p.constractor == People; // true
2.原型對象
每一個js對象中. 都有一個隱藏屬性 __proto__
指向該對象的 原型對象
. 在執(zhí)行該對象的方法或者查找屬性時. 首先, 對象自己是否存在該屬性或者方法. 如果存在, 就執(zhí)行自己的. 如果自己不存在. 就去找 原型對象
.
function Friend(){ this.chi = function(){ console.log("我的朋友在吃"); } } Friend.prototype.chi = function(){ console.log("我的原型在吃") } f = new Friend(); f.chi(); // 此時. 該對象中. 有chi這個方法. 同時, 它的原型對象上, 也有chi這個方法. // 運行結(jié)果: // 我的朋友在吃
3.prototype
和 __proto__
有什么關(guān)系?
在js中. 構(gòu)造器的prototype屬性和對象的 __proto__
是一個東西. 都是指向這個 原型對象
.
f.__proto__ === Friend.prototype // true
4.原型鏈
這個比較繞了. 我們從前面的學(xué)習(xí)中, 了解到. 每個對象身體里. 都隱藏著 __proto__
也就是它的 原型對象
. 那么我們看哈, 原型對象
也是 對象
啊, 那么也就是說. 原型對象
也有 __proto__
屬性.
類似于.....這樣:
f.__proto__.__proto__
打印出來的效果是這樣的:
此時. 又出現(xiàn)一堆看不懂的玩意. 這些玩意是什么? 這些其實是Object的原型.
f.__proto__.__proto__ === Object.prototype
所以, 我們在執(zhí)行 f.toString()
的時候不會報錯. 反而可以正常運行. 原因就在這里.
執(zhí)行過程: 先找 f對象
中是否有 toString
. 沒有, 找它的 原型對象
. 原型對象
中沒有, 繼續(xù)找 原型對象的原型對象
. 直至你找到Object的原型為止. 如果還是沒有. 就報錯了.
f.hahahahahahah() // 報錯.
綜上, 原型鏈?zhǔn)莏s 方法查找的路徑指示標(biāo)
.
5. 我們用原型鏈能做什么?(每日一惡心)
我們來看一段神奇的代碼.
(function(){debugger})();
這樣一段代碼可以看到. 瀏覽器進入了debugger斷點.
那么這段代碼的背后是什么呢? 注意. 在js代碼執(zhí)行時. 每一個function的對象都是通過Function()來創(chuàng)建的. 也就是說. 函數(shù)是Function()的對象.
function fn(){}
console.log(fn.proto.constructor); // ƒ Function() { [native code] }
那么這段代碼的背后是什么呢? 注意. 在js代碼執(zhí)行時. 每一個function的對象都是通過Function()來創(chuàng)建的. 也就是說. 函數(shù)是Function()的對象.
function fn(){} console.log(fn.__proto__.constructor); // ? Function() { [native code] }
函數(shù)就是Function的對象. 那么. 我們可以通過Function來構(gòu)建一個函數(shù).
new Function('debugger')();
OK. 這東西對我們來說有什么用. 上代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="haha.js"></script> <script> txsdefwsw(); </script> </head> <body> 有內(nèi)鬼. 終止交易 </body> </html>
haha.js 中的內(nèi)容如下:
function txsdefwsw() { var r = "V", n = "5", e = "8"; function o(r) { if (!r) return ""; for (var t = "", n = 44106, e = 0; e < r.length; e++) { var o = r.charCodeAt(e) ^ n; n = n * e % 256 + 2333, t += String.fromCharCode(o) } return t } try { var a = ["r", o("?"), "g", o("?"), function (t) { if (!t) return ""; for (var o = "", a = r + n + e + "7", c = 45860, f = 0; f < t.length; f++) { var i = t.charCodeAt(f); c = (c + 1) % a.length, i ^= a.charCodeAt(c), o += String.fromCharCode(i) } return o }("@"), "b", "e", "d"].reverse().join(""); !function c(r) { (1 !== ("" + r / r).length || 0 === r) && function () { }.constructor(a)(), c(++r) }(0) } catch (a) { setTimeout(txsdefwsw, 100); } }
頁面跑起來沒什么問題. 但是會無限debugger;
解決方案:
- 找到斷點出. 右鍵-> never pause here;
- 寫js hook代碼;
var x = Function; // 保留原來的Function Function = function(arg){ arg = arg.replace("debugger", ""); return new x(arg); } var qiaofu_function_constructor = (function(){}).__proto__.constructor; (function(){}).__proto__.constructor = function(arg){ console.log("我愛你大大"); if(arg ==='debugger'){ return function(){} } else { return new qiaofu_function_constructor(arg); } }
[[prototype]] __proto__ 構(gòu)造器.prototype function jiami(){ } jiami.prototype.md5 = function(){} jiami.prototype.aes = function(){} jiami.prototype.encrypt = function(){} var s = new jiami(); s.md5();
到此這篇關(guān)于JavaScript關(guān)于prototype(超重點)的文章就介紹到這了,更多相關(guān)js 關(guān)于prototype內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js中獲取鍵盤按下鍵值event.keyCode、event.charCode和event.which的兼容性詳解
這篇文章主要給大家介紹了關(guān)于Javascript中獲取鍵盤按下鍵值event.keyCode、event.charCode和event.which的兼容性的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-03-03JavaScript中數(shù)組雙重去重的方法總結(jié)
這篇文章主要為大家學(xué)習(xí)介紹了JavaScript中數(shù)組雙重去重的幾個常用方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-07-07JavaScript實現(xiàn)的原生態(tài)兼容IE6可調(diào)可控滾動文字功能詳解
這篇文章主要介紹了JavaScript實現(xiàn)的原生態(tài)兼容IE6可調(diào)可控滾動文字功能,簡單說明了文字滾動的實現(xiàn)原理并結(jié)合具體實例形式給出了javascript文字滾動功能的具體實現(xiàn)代碼,需要的朋友可以參考下2017-09-09JS實現(xiàn)動態(tài)添加DOM節(jié)點和事件的方法示例
這篇文章主要介紹了JS實現(xiàn)動態(tài)添加DOM節(jié)點和事件的方法,涉及javascript事件響應(yīng)及針對頁面dom元素節(jié)點與屬性的動態(tài)操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2017-04-04微信小程序setInterval定時函數(shù)新手使用的超詳細(xì)教程
平時開發(fā)中為實現(xiàn)倒計時效果可以使用setInterval即可,下面這篇文章主要給大家介紹了關(guān)于微信小程序setInterval定時函數(shù)新手使用的超詳細(xì)教程,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08網(wǎng)頁中右鍵功能的實現(xiàn)方法之contextMenu的使用
本文介紹一種網(wǎng)頁中實現(xiàn)右鍵功能的方案–contextMenu,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-02-02