进阶 2 - JS中的各种操作(非交互)

定时器

在JS中, 有两种设置定时器的方案

// 语法规则
t = setTimeout(函数, 时间)
// 经过xxx时间后, 执行xxx函数

// 示例:3秒后打印我爱你
t = setTimeout(function () {
    console.log("我爱你")
}, 3000);

window.clearTimeout(t) // 停止一个定时器

eval 函数

eval本身在js里面正常情况下使用的并不多. 但是很多网站会利用eval的特性来完成反爬操作. 我们来看看eval是个什么鬼?

从功能上讲, eval非常简单. 它和python里面的eval是一样的. 它可以动态的把字符串当成js代码进行运行.

s = "console.log('我爱你')";
eval(s);

也就是说. eval里面传递的应该是即将要执行的代码(字符串). 那么在页面中如果看到了eval加密该如何是好? 其实只要记住了一个事儿. 它里面不论多复杂. 一定是个字符串.

比如,

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0.1(\'我爱你\')',62,2,'console|log'.split('|'),0,{}))

这一坨看起来, 肯定很不爽. 怎么变成我们看着很舒服的样子呢? 记住. eval()里面是字符串. 记住~!!

那我想看看这个字符串长什么样? 就把eval()里面的东西拷贝出来. 执行一下. 最终一定会得到一个字符串. 要不然eval()执行不了的. 对不...于是就有了下面的操作.

http://tools.jb51.net/password/evalencode, 再赠送你一个在线JS处理eval的网站. 大多数的eval加密. 都可以搞定了。

prototype和__proto__

逆向代码示例:

function ct(t) {
    pv['$_BCAO'] = t || [];
}

ct.prototype = {
    '$_CAE':function(f) {
               f();
            }
} 

var H = new ct(t)['$_CAE'](function(t) {
        var e = function(t) {
            for (var e = [[1, 0], [2, 0], [1, -1], [1, 1], [0, 1], [0, -1], [3, 0], [2, -1], [2, 1]], r = e['length'],n = 0; n < r; n++){
                var b = 'stuvwxyz~';
            }   
            return b;
        };
      return e;
    })

示例:

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();

我现在代码写完了. 突然之间, 我感觉好像少了个功能. 人不应该就一个功能. 光会跑是不够的. 还得能够学习. 怎么办? 直接改代码? 可以. 但不够好. 如果这个代码封装不是我写的呢? 随便改别人代码是很不礼貌的. 也很容易出错. 怎么办? 我们可以在我们自己代码中对某个类型动态增加功能. 此时就用到了prototype.

//对象的模版:类
function People(name, age){
    this.name = name;
    this.age = age;
    this.run = function(){
        console.log(this.name+"在跑")
    }
}

//People.prototype原型对象
People.prototype.address = "Beijing";
// 通过prototype可以给People增加功能
People.prototype.study = function(){
    console.log(this.name+"还可以学习");
}
//通过对象模版创建的实例对象
var p1 = new People("张三", 18);
var p2 = new People("李四", 19);

p1.run();
p2.run();

p1.study();
p2.study();

能看到一些效果了是吧. 也就是说. 可以通过prototype给我们的对象增加一些功能. 那么,什么是prototype呢?

接下来. 聊几个重要的概念.

1. 原型对象

每一个js对象中. 都有一个隐藏属性__proto__指向该对象的原型对象. (People.prototype)

原型对象用于存储所有实例对象共享的属性和方法,以减少每个实例对象重复存储相同属性和方法的开销。

在执行该对象的方法或者查找属性时. 首先, 对象自己是否存在该属性或者方法. 如果存在, 就执行自己的. 如果自己不存在. 就去找原型对象.

p1.toString()
// 显然p1对象是没有该方法的,但是确实可以调用该方法,
// 通过查看p1的原型,发现在Object中存在toString方法。

实例对象是可以共享它的原型链上所有的原型对象存在的成员

对象的原型成员重写:

function Friend(){
    this.chi = function(){
        console.log("我的朋友在吃");
    }
}
Friend.prototype.chi = function(){
    console.log("我的原型在吃")
}

f = new Friend();
f.chi(); // 此时,该对象中有chi这个方法.  同时, 它的原型对象上, 也有chi这个方法.
// 运行结果: 我的朋友在吃

2. prototype__proto__有什么关系?

在js中. 函数名的prototype属性和对象的__proto__是一个东西. 都是指向这个原型对象.

f.__proto__ === Friend.prototype   // true

3. 原型链

原型链是JavaScript中对象继承属性和方法的一种方式。具体介绍如下:

原型链是JavaScript中对象继承属性和方法的一种方式。
当访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,
它会通过原型链去它的原型对象中查找,如果原型对象也没有,
会继续在其原型的原型中查找,这样逐级向上,直到找到属性或方法或者达到原型链的末端。

这个比较绕了. 我们从前面的学习中, 了解到. 每个对象身体里. 都隐藏着__proto__也就是它的原型对象. 那么我们看哈, 原型对象也是对象啊, 那么也就是说. 原型对象也有__proto__属性.

类似于.....这样:

f.__proto__.__proto__

此时. 又出现一堆看不懂的玩意. 这些玩意是什么? 这些其实是Object的原型.

f.__proto__.__proto__ === Object.prototype

练习测试:理解下属代码

function ct(t) {
    pv['$_BCAO'] = t || [];
}

var H = new ct(t)['$_CAE'](function(t) {
        var e = function(t) {
            for (var e = [[1, 0], [2, 0], [1, -1], [1, 1], [0, 1], [0, -1], [3, 0], [2, -1], [2, 1]], r = e['length'],n = 0; n < r; n++){
                var b = 'stuvwxyz~';
            }   
            return b;
        };
      return e;
    })

ct.prototype = {
    '$_CAE':function(f) {
               f();
            }
}

重点总结:

  1. prototype关键字是可以给对象动态添加成员

  2. 原型对象中的成员是可以被所有实例对象共享

  3. 对象在调用某一个成员时,该成员有可能是对象自身封装的成员也可能是该对象原型上的成员

Last updated