13 JavaScript关于prototype(超重点)

  • 13 JavaScript关于prototype(超重点)已关闭评论
  • 166 次浏览
  • A+
所属分类:Web前端
摘要

13 JavaScript关于prototype(超重点)prototype是js里面给类增加功能扩展的一种模式.
写个面向对象来看看.

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 
  1. 原型对象
    每一个js对象中. 都有一个隐藏属性__proto__指向该对象的原型对象. 在执行该对象的方法或者查找属性时. 首先, 对象自己是否存在该属性或者方法. 如果存在, 就执行自己的. 如果自己不存在. 就去找原型对象.
function Friend(){     this.chi = function(){         console.log("我的朋友在吃");     } } Friend.prototype.chi = function(){     console.log("我的原型在吃") }  f = new Friend(); f.chi(); // 此时. 该对象中. 有chi这个方法.  同时, 它的原型对象上, 也有chi这个方法. // 运行结果: // 我的朋友在吃 
  1. prototype__proto__有什么关系?
    在js中. 构造器的prototype属性和对象的__proto__是一个东西. 都是指向这个原型对象.
f.__proto__ === Friend.prototype   // true 
  1. 原型链
    这个比较绕了. 我们从前面的学习中, 了解到. 每个对象身体里. 都隐藏着__proto__也就是它的原型对象. 那么我们看哈, 原型对象也是对象啊, 那么也就是说. 原型对象也有__proto__属性.

类似于.....这样:

f.__proto__.__proto__ 

打印出来的效果是这样的:
13 JavaScript关于prototype(超重点)
此时. 又出现一堆看不懂的玩意. 这些玩意是什么? 这些其实是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; // 保留原来的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);   	}   } 

13 JavaScript关于prototype(超重点)

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