JavaScript关于prototype实例详解(超重点)
作者:生而自由爱而无畏
JavaScript关于prototype(超重点)
prototype是js里面给类增加功能扩展的一种模式.写个面向对象来看看.
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();
我现在代码写完了. 突然之间, 我感觉好像少了个功能. 人不应该就一个功能. 光会跑是不够的. 还得能够ooxx. 怎么办? 直接改代码? 可以. 但不够好. 如果这个类不是我写的呢? 随便改别人代码是很不礼貌的. 也很容易出错. 怎么办? 我们可以在我们自己代码中对某个类型动态增加功能. 此时就用到了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.构造器
构造一个对象的函数. 叫构造器.
function People(){ //这个东西就是构造器 constractor } var p = new People(); // 调用构造器 p.constractor == People; // true
2.原型对象
每一个js对象中. 都有一个隐藏属性 __proto__
指向该对象的 原型对象
. 在执行该对象的方法或者查找属性时. 首先, 对象自己是否存在该属性或者方法. 如果存在, 就执行自己的. 如果自己不存在. 就去找 原型对象
.
function Friend(){ this.chi = function(){ console.log("我的朋友在吃"); } } Friend.prototype.chi = function(){ console.log("我的原型在吃") } f = new Friend(); f.chi(); // 此时. 该对象中. 有chi这个方法. 同时, 它的原型对象上, 也有chi这个方法. // 运行结果: // 我的朋友在吃
3.prototype
和 __proto__
有什么关系?
在js中. 构造器的prototype属性和对象的 __proto__
是一个东西. 都是指向这个 原型对象
.
f.__proto__ === Friend.prototype // true
4.原型链
这个比较绕了. 我们从前面的学习中, 了解到. 每个对象身体里. 都隐藏着 __proto__
也就是它的 原型对象
. 那么我们看哈, 原型对象
也是 对象
啊, 那么也就是说. 原型对象
也有 __proto__
属性.
类似于.....这样:
f.__proto__.__proto__
打印出来的效果是这样的:
此时. 又出现一堆看不懂的玩意. 这些玩意是什么? 这些其实是Object的原型.
f.__proto__.__proto__ === Object.prototype
所以, 我们在执行 f.toString()
的时候不会报错. 反而可以正常运行. 原因就在这里.
执行过程: 先找 f对象
中是否有 toString
. 没有, 找它的 原型对象
. 原型对象
中没有, 继续找 原型对象的原型对象
. 直至你找到Object的原型为止. 如果还是没有. 就报错了.
f.hahahahahahah() // 报错.
综上, 原型链是js 方法查找的路径指示标
.
5. 我们用原型链能做什么?(每日一恶心)
我们来看一段神奇的代码.
(function(){debugger})();
这样一段代码可以看到. 浏览器进入了debugger断点.
那么这段代码的背后是什么呢? 注意. 在js代码执行时. 每一个function的对象都是通过Function()来创建的. 也就是说. 函数是Function()的对象.
function fn(){}
console.log(fn.proto.constructor); // ƒ Function() { [native code] }
那么这段代码的背后是什么呢? 注意. 在js代码执行时. 每一个function的对象都是通过Function()来创建的. 也就是说. 函数是Function()的对象.
function fn(){} console.log(fn.__proto__.constructor); // ƒ Function() { [native code] }
函数就是Function的对象. 那么. 我们可以通过Function来构建一个函数.
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> 有内鬼. 终止交易 </body> </html>
haha.js 中的内容如下:
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__ 构造器.prototype function jiami(){ } jiami.prototype.md5 = function(){} jiami.prototype.aes = function(){} jiami.prototype.encrypt = function(){} var s = new jiami(); s.md5();
到此这篇关于JavaScript关于prototype(超重点)的文章就介绍到这了,更多相关js 关于prototype内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!