当前位置: 首页 > article >正文

13 JavaScript 关于prototype(超重点)

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

打印出来的效果是这样的:

image

 此时. 又出现一堆看不懂的玩意. 这些玩意是什么? 这些其实是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] }
这样一段代码可以看到. 浏览器进入了debugger断点.

那么这段代码的背后是什么呢? 注意. 在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;

解决方案:

  1. 找到断点出. 右键-> never pause here;
  2. 写js hook代码;
var x = Function; // 保留原来的FunctionFunction = 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);}}

image

[[prototype]]
__proto__
构造器.prototype
function jiami(){}
jiami.prototype.md5 = function(){}
jiami.prototype.aes = function(){}
jiami.prototype.encrypt = function(){}
var s = new jiami();
s.md5();

http://www.lryc.cn/news/2417555.html

相关文章:

  • HTTP状态码、accept与content-type
  • 明日之后怎么找不到朋友服务器,明日之后搜索不到好友 搜索添加好友教程
  • CentOS7.6安装ORACLE 12C RAC + DATAGUARD
  • 安卓逆向Xposed HOOK TB APP的x-sign参数
  • 如何辨别真假IPHONE4 , IPHONE 4S ?
  • 字节跳动高工面试-Android-R如何访问文件、修改文件?你们对R适配了吗?(1)
  • 报错的解决 sqlite3.OperationalError: unrecognized token: “630008.OF“
  • 手游自动挂机脚本开发历程
  • 上古卷轴5天际重置版d3dx9_42.dll丢失怎么办?全面解析上古卷轴5天际重置版d3dx9_42.dll丢失问题的解决方案
  • 纳尼亚传奇2 片尾曲
  • 分布式数据库是如何实现高可用的?
  • 点评国内Facebook克隆网站 - SNS之我见(二)
  • ASP.NET虚拟主机安全漏洞解决方案 【 这篇文章不错 】
  • 联通版中兴V880终于被“破坏之王”360给Root了
  • 虚拟机中安装Linux(Redhat)教程
  • 思科模拟器教程-RIP、OSPF路由协议重发布
  • 一:使用FreeIPA安装Kerberos和LDAP
  • 分享几个特别特别强的资源福利网站
  • Android 平台版本所支持的 API 级别
  • 资源下载新体验:五款高效下载工具深度盘点
  • 超级玩家官方论坛android版,超级玩家官方论坛
  • 中国香港交易所股票行情数据API接口
  • 敏捷-意淫者的天堂
  • 常用Javsscript(一)
  • 小小作品flash_再见了,Flash!
  • [Andriod] fastboot 和 recovery 模式的区别
  • 大数据分析在社交媒体广告流量优化中的重要作用
  • Unity面试题(含答案)
  • 51单片机LCD1602程序
  • 彻底放弃IIS 让Apache也支持ASP.NET