(78)Wangdao.com第十五天_JavaScript 面向对象
面向对象编程(Object Oriented Programming,缩写为 OOP)
是目前主流的编程范式。
是单个实物的抽象,
是一个容器,封装了属性(property)和方法(method),属性是对象的状态,方法是对象的行为(完成某种任务)。
将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。
每一个对象都是功能中心,具有明确分工,可以完成接受信息、处理数据、发出信息等任务。
对象可以复用,通过继承机制还可以定制。
具有灵活、代码可复用、高度模块化等特点,容易维护和开发,比起由一系列函数或指令组成的传统的过程式编程(procedural programming),更适合多人合作的大型软件项目。
- 构造函数
“类” 就是对象的模板,对象就是 “类” 的实例。
JavaScript 语言的对象体系,不是基于“类”的,而是基于构造函数(constructor)和原型链(prototype)。
- 使用构造函数(constructor)作为对象的模板,描述实例对象的基本结构。。
- 所谓 ”构造函数”,就是专门用来生成实例对象的函数。
- 一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。
- 为了与普通函数区别,构造函数名字的第一个字母通常大写。
- 特点:
- 函数体内部使用了
this
关键字,代表所要生成的实例 - 生成对象的时候,必须使用
new
命令
- 函数体内部使用了
- new 命令
- 通过
new
命令,让构造函数生成一个实例对象 new
命令执行时,构造函数内部的this
,就代表了新生成的实例对象- 使用
new
命令时,根据需要,构造函数也可以接受参数- var Vehicle = function (p) {
- this.price = p;
- };
- var v = new Vehicle(500);
new
命令本身就可以执行构造函数,所以后面的构造函数可以带括号,也可以不带括号。但是为了表示是函数调用,推荐使用括号- var Vehicle = function (p) {
- var Vehicle = function (){
- this.price = 1000;
- };
- var v = Vehicle(); // 将构造函数当成普通函数调用,不抱错
- v // undefined // 但是变量v变成了undefined
- price // 1000 // price属性变成了全局变量
- // 一个解决办法是:
- // 构造函数内部使用严格模式,即第一行加上use strict。
- // 这样的话,一旦忘了使用new命令,直接调用构造函数就会报错。
function Fubar(foo, bar){
'use strict';
this._foo = foo; // 由于 严格模式中,函数内部的
this
不能指向全局对象,默认等于undefined
this._bar = bar;
}
Fubar(); // TypeError: Cannot set property '_foo' of undefined
// 另一个解决办法:
// 造函数内部判断是否使用new
命令,如果发现没有使用,则直接返回一个实例对象。
function Fubar(foo, bar) {
if (!(this instanceof Fubar)) {
return new Fubar(foo, bar);
}
this._foo = foo;
this._bar = bar;
}
// 此时不管加不加new
命令,都会得到同样的结果Fubar(1, 2)._foo // 1
(new Fubar(1, 2))._foo // 1
- var Vehicle = function (){
- 通过
- new 命令的原理
使用new
命令时,它后面的函数依次执行下面的步骤
1. 创建一个空对象,作为将要返回的对象实例
2. 将这个空对象的隐式原型对象 __proto__,指向构造函数的 prototype 属性
3. 将这个空对象赋值给函数内部的 this 关键字
4. 开始执行构造函数内部的代码
- 如果构造函数内部有 return 语句,而且 return 后面跟着一个对象,new 命令会返回 return 语句指定的对象;否则,就会不管 return 语句,返回 this 对象
- 如果对普通函数(内部没有
this
关键字的函数)使用new
命令,则会返回一个空对象 - 因为
new
命令总是返回一个对象,要么是实例对象,要么是return
语句指定的对象- function getMessage() {
- return 'this is a message';
- }
- var msg = new getMessage();
- msg // {}
- typeof msg // "object"
- function getMessage() {
- 如果对普通函数(内部没有
new
命令简化的内部流程,可以用下面的代码表示- function _new(/* 构造函数 */ constructor, /* 构造函数参数 */ params) {
- // 将 arguments 对象转为数组
- var args = [].slice.call(arguments);
- // 取出构造函数
- var constructor = args.shift();
- // 创建一个空对象,继承构造函数的 prototype 属性
- var context = Object.create(constructor.prototype);
- // 执行构造函数
- var result = constructor.apply(context, args);
- // 如果返回结果是对象,就直接返回,否则返回 context 对象
- return (typeof result === 'object' && result != null) ? result : context;
- }
- // 实例
- var actor = _new(Person, '张三', 28);
- function _new(/* 构造函数 */ constructor, /* 构造函数参数 */ params) {
- 如果构造函数内部有 return 语句,而且 return 后面跟着一个对象,new 命令会返回 return 语句指定的对象;否则,就会不管 return 语句,返回 this 对象
- 函数内部可以使用 new.target 属性
- 如果当前函数是
new
命令调用,new.target
指向当前函数,否则为undefined
- function f() {
- console.log(new.target === f);
- }
- f(); // false //
new.target
指向undefined
- new f(); // true //
new.target
指向 当前函数
- function f() {
- 使用这个属性,可以判断函数调用的时候,是否使用
new
命令- function f() {
- if (!new.target) {
- throw new Error('请使用 new 命令调用!');
- }
- // ...
- }
- f(); // Uncaught Error: 请使用 new 命令调用!
- function f() {
- 如果当前函数是
- Object.create() 创建实例对象
- 有时拿不到构造函数,只能拿到一个现有的对象
- 可以使用 Object.create() 方法,生成新的实例对象
- var Person= {
- name: '张三',
- age: 38,
- greeting: function() {
- console.log('Hi! I\'m ' + this.name + '.');
- }
- };
- var person2 = Object.create(Person);
- person2.name; // 张三
- person2.greeting(); // Hi! I'm 张三.
- var Person= {
- this 关键字
this除了可以在构造函数中表示实例对象,还可以用在其他场合
但是不管什么场合,this 总是返回一个对象
- this 的指向是可变的
- 只要函数被赋给另一个变量,this 的指向就会变
- var A = {
- name: '张三',
- describe: function () {
- return '姓名:'+ this.name;
- }
- };
- var name = '李四'; // window.name
- var f = A.describe; // window.f
- f(); // "姓名:李四"
- var A = {
- 根据据当前所在的对象不同,this 的指向也不同
- function f() {
- return '姓名:'+ this.name;
- }
- var A = {
- name: '张三',
- describe: f
- };
- var B = {
- name: '李四',
- describe: f
- };
- A.describe(); // "姓名:张三"
- B.describe(); // "姓名:李四"
- function f() {
- 一个网页编程的例子
- <input type="text" name="age" size=3 onChange="validate(this, 18, 99);">
- <script>
- function validate(obj, lowval, hival){
- if ((obj.value < lowval) || (obj.value > hival))
- console.log('Invalid Value!');
- }
- </script>
// 一个文本输入框,每当用户输入一个值,就会调用onChange
回调函数,验证这个值是否在指定范围。
// 浏览器会向回调函数传入当前对象,因此this
就代表传入当前对象(即文本框),然后就可以从obj.value
上面读到用户的输入值
JavaScript 支持运行环境动态切换,也就是说,
this
的指向是动态的,没有办法事先确定到底指向哪个对象
- 只要函数被赋给另一个变量,this 的指向就会变
- this 实质
- var obj = { foo: 5 };
- // 原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。
- // 举例来说,上面例子的 foo 属性,实际上是以下面的形式保存的
- {
- foo: {
- [[value]]: 5
- [[writable]]: true
- [[enumerable]]: true
- [[configurable]]: true
- }
- }
- var obj = { foo: 5 };
- 有 this 的设计,跟内存里面的数据结构有关系
- 由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行
- 由于函数可以在 不同的运行环境(上下文) 执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)
- 所以,this 就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
- var f = function () {
- console.log(this.x);
- }
- var x = 1;
- var obj = {
- ff: f,
- x: 2,
- };
- // 单独执行
- f(); //
- // obj 环境执行
- obj.ff(); //
- var f = function () {
- 几个使用场合下,this 的指向
- 全局环境
- 全局环境使用this,它指的就是顶层对象window
- 不管是不是在函数内部,只要是在全局环境下运行,this 就是指顶层对象window
- 构造函数
- 构造函数中的 this ,指的是实例对象构造函数中的 this ,指的是实例对象
- 方法调用时
- this 指向调用该对象的对象。
- call() 和 apply() 时
- 指向指定的对象
- 全局环境
- 有 this 的设计,跟内存里面的数据结构有关系
- 由于 this 的指向是不确定的,所以切勿在函数中包含多层的 this
- 使用一个变量固定 this 的值,然后内层函数调用这个变量,是非常常见的做法,请务必掌握
- var o = {
- f1: function () {
- console.log(this);
- var f2 = function () {
- console.log(this);
- }();
- }
- }
- o.f1();
- // Object
- // Window
- var o = {
- 使用一个变量固定 this 的值,然后内层函数调用这个变量
- var o = {
- f1: function() {
- console.log(this);
- var that = this;
- var f2 = function() {
- console.log(that);
- }();
- }
- }
- o.f1()
- // Object
- // Object
- // 以上代码等价于
var temp = function () {
console.log(this);
};
var o = {
f1: function () {
console.log(this);
var f2 = temp();
}
}
- var o = {
- 严格模式下,如果函数内部的 this 指向顶层对象,就会报错。
- 由于 this 的指向是不确定的,所以切勿在函数中包含多层的 this
- 避免数组处理方法中的 this
- 数组的
map
和foreach
方法,允许提供一个函数作为参数。这个函数内部不应该使用this
- 如果有
- 使用中间变量固定this
- 将 this 当作 foreach( , this) 方法的第二个参数,固定它的运行环境
- var o = {
- v: 'hello',
- p: [ 'a1', 'a2' ],
- f: function f() {
- this.p.forEach(function (item) {
- console.log(this.v + ' ' + item);
- });
- }
- }
- o.f()
- // undefined a1
- // undefined a2
- // 解决方法1 使用变量固定 this
- var o = {
- v: 'hello',
- p: [ 'a1', 'a2' ],
- f: function f() {
- var that = this;
- this.p.forEach(function (item) {
- console.log(that.v+' '+item);
- });
- }
- }
- o.f()
- // hello a1
- // hello a2
- // 解决方法2 forEach( , this)
- var o = {
- v: 'hello',
- p: [ 'a1', 'a2' ],
- f: function f() {
- this.p.forEach(function (item) {
- console.log(this.v + ' ' + item);
- }, this);
- }
- }
- o.f()
- // hello a1
- // hello a2
- var o = {
- 数组的
- 回调函数中的 this 往往会改变指向,最好避免使用
- var o = new Object();
- o.f = function () {
- console.log(this === o);
- }
- // jQuery 的写法
- $('#button').on('click', o.f);
上面代码中,点击按钮以后,控制台会显示
false
。原因是此时this
不再指向o
对象,而是指向按钮的 DOM 对象,因为f
方法是在按钮对象的环境中被调用的。- var o = new Object();
- 避免数组处理方法中的 this
- 固定 this 指向
JavaScript 提供了call
、apply
、bind
这三个方法,来切换/固定this
的指向
- Function.prototype.call()
- 函数实例的call方法,可以指定函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数
- var obj = {};
- var f = function () {
- return this;
- };
- f() === window // true
- f.call(obj) === obj // true
- call 方法的参数,应该是一个对象。如果参数为空、null和undefined,则默认传入全局对象
- 如果 call 方法的参数是一个原始值,那么这个原始值会自动转成对应的包装对象,然后传入 call 方法
- var f = function () {
- return this;
- };
- f.call(5)
- // Number {[[PrimitiveValue]]: 5}
- var f = function () {
- call 方法还可以接受多个参数 func.call(thisObj, arg1, arg2, ...)
- 后面的参数是函数调用时所需的参数
- function add(a, b) {
- return a + b;
- }
- add.call(this, 1, 2); //
- function add(a, b) {
- 应用 之 调用对象的原生方法
- var obj = {};
- obj.hasOwnProperty('toString'); // false
- // 覆盖掉继承的 hasOwnProperty 方法
- obj.hasOwnProperty = function () {
- return true;
- };
- obj.hasOwnProperty('toString'); // true
- // hasOwnProperty是obj对象继承的方法,如果这个方法一旦被覆盖,就不会得到正确结果
- // 将hasOwnProperty方法的原始定义放到obj对象上执行,这样无论obj上有没有同名方法,都不会影响结果
- Object.prototype.hasOwnProperty.call(obj, 'toString'); // false
- var obj = {};
- 如果 call 方法的参数是一个原始值,那么这个原始值会自动转成对应的包装对象,然后传入 call 方法
- Function.prototype.apply()
- 与 call 方法类似,也是改变 this 指向,然后再调用该函数。
- 唯一的区别就是,它只有 2 个参数,第二个参数接收一个数组作为函数执行时的参数 func.call(thisObj, [arg1, arg2, ...])
- 第一个参数也是 this 所要指向的那个对象,如果设为null或undefined,则等同于指定全局对象
- 很多有趣的应用
- 找出数组最大元素
- var a = [10, 2, 4, 15, 9];
- // 结合使用apply方法和Math.max方法,就可以返回数组的最大元素
- Math.max.apply(null, a); //
- 将数组的空元素变为 undefined
- // 利用 Array构造函数 和 apply结合
- // 将数组的空元素变成undefined
- Array.apply(null, ['a', ,'b']); // [ 'a', undefined, 'b' ]
空元素与undefined的差别在于,数组的forEach方法会跳过空元素,但是不会跳过undefined
- // 利用 Array构造函数 和 apply结合
- 转换类似数组的对象
- 利用数组对象的slice方法,将一个类似数组的对象(比如arguments对象)转为真正的数组
- // 前提是
- //被处理的对象必须有length属性
- //以及相对应的数字键
- Array.prototype.slice.apply({0: 1, length: 1}); // [1]
- Array.prototype.slice.apply({0: 1}); // []
- Array.prototype.slice.apply({0: 1, length: 2}); // [1, undefined]
- Array.prototype.slice.apply({length: 1}); // [undefined]
- // 前提是
- 绑定回调函数的对象
- var o = new Object();
- o.f = function () {
- console.log(this === o);
- }
- var f = function (){
- o.f.apply(o); // 或者 o.f.call(o);
- };
- // jQuery 的写法
- $('#button').on('click', f);
- //点击按钮以后,控制台将会显示true。
- // 由于apply方法(或者call方法)不仅绑定函数执行时所在的对象,还会立即执行函数,因此不得不把绑定语句写在一个函数体内。
- // 更简洁的写法是采用下面介绍的bind方法。
- 找出数组最大元素
- Function.prototype.bind()
- 用于将函数体内的 this 绑定到某个对象,然后返回一个新函数
- var d = new Date();
- d.getTime() //
- var print = d.getTime;
- print() // Uncaught TypeError: this is not a Date object.
- // 因为getTime方法内部的this,绑定Date对象的实例,赋给变量print以后,内部的this已经不指向Date对象的实例了
bind方法可以解决这个问题
- var print = d.getTime.bind(d);
- print(); //
bind 方法将 getTime 方法内部的 this 绑定到 d 对象,这时就可以安全地将这个方法赋值给其他变量了
- var print = d.getTime.bind(d);
- var d = new Date();
- bind 方法的参数就是所要绑定 this 的对象
- 下面是一个更清晰的例子
- var counter = {
- count: 0,
- inc: function () {
- this.count++;
- }
- };
- var func = counter.inc.bind(counter);
- func();
- counter.count //
counter.inc() 方法被赋值给变量 func 。这时必须用 bind 方法将 inc 内部的 this,绑定到 counter,否则就会出错
- var counter = {
- this绑定到其他对象也是可以的
- var counter = {
- count: 0,
- inc: function () {
- this.count++;
- }
- };
- var obj = {
- count: 100
- };
- var func = counter.inc.bind(obj);
- func();
- obj.count //
- var counter = {
- bind 还可以接受更多的参数,将这些参数绑定原函数的参数
- var add = function (x, y) {
- return x * this.m + y * this.n;
- }
- var obj = {
- m: 2,
- n: 2
- };
- var newAdd = add.bind(obj, 5);
- newAdd(5) //
bind() 方法除了绑定 this 对象,还将 add 函数的第一个参数 x 绑定成 5,然后返回一个新函数 newAdd(),这个函数只要再接受一个参数 y 就能运行了
- var add = function (x, y) {
- 如果bind() 方法的第一个参数是 null 或 undefined,等于将 this 绑定到全局对象,函数运行时 this 指向顶层对象(浏览器为window)
- function add(x, y) {
- return x + y;
- }
- var plus5 = add.bind(null, 5);
- plus5(10); //
上面代码中,函数 add 内部并没有 this,使用 bind() 方法的主要目的是绑定参数 x,以后每次运行新函数 plus5,就只需要提供另一个参数 y 就够了。
- function add(x, y) {
而且因为 add 内部没有 this,所以 bind() 的第一个参数是 null,不过这里如果是其他对象,也没有影响
- bind() 使用注意
- 每一次返回一个新函数
- bind方法每运行一次,就返回一个新函数,这会产生一些问题。
- 比如,监听事件的时候,不能写成下面这样
- element.addEventListener('click', o.m.bind(o));
- // 上面代码中,click事件绑定bind方法生成的一个匿名函数。
- // 这样会导致无法取消绑定,所以,下面的代码是无效的
- element.removeEventListener('click', o.m.bind(o));
- // 正确写法
- var listener = o.m.bind(o);
- element.addEventListener('click', listener);
- // ...
- element.removeEventListener('click', listener);
- element.addEventListener('click', o.m.bind(o));
- 结合回调函数使用
- 回调函数是 JavaScript 最常用的模式之一,
- 但是一个常见的错误是,将包含 this 的方法直接当作回调函数
- var counter = {
- count: 0,
- inc: function () {
- 'use strict';
- this.count++;
- }
- };
- function callIt(callback) {
- callback();
- }
// 上面代码中,callIt方法会调用回调函数。
// 这时如果直接把counter.inc传入,调用时counter.inc内部的this就会指向全局对象。- callIt(counter.inc.bind(counter)); // 使用bind方法将counter.inc绑定counter以后,就不会有这个问题,this总是指向counter
- counter.count //
- var counter = {
- 某些数组方法可以接受一个函数当作参数。这些函数内部的
this
指向,很可能也会出错- var obj = {
- name: '张三',
- times: [1, 2, 3],
- print: function () {
- this.times.forEach(function (n) {
- console.log(this.name);
- });
- }
- };
- obj.print(); // 没有任何输出
- // obj.print内部this.times的this是指向obj的,这个没有问题。
- // 但是,forEach方法的回调函数内部的this.name却是指向全局对象,导致没有办法取到值。
- obj.print = function () {
- this.times.forEach(function (n) {
- console.log(this === window);
- });
- };
- obj.print()
- // true
- // true
- // true
解决方法
- // 通过bind方法绑定this
- obj.print = function () {
- this.times.forEach(function (n) {
- console.log(this.name);
- }.bind(this));
- };
- obj.print()
- // 张三
- // 张三
- // 张三
- // 通过bind方法绑定this
- var obj = {
- 结合call方法使用
- 利用bind方法,可以改写一些 JavaScript 原生方法的使用形式,以数组的slice方法为例
- [1, 2, 3].slice(0, 1); // [1]
- // 等同于
- Array.prototype.slice.call([1, 2, 3], 0, 1); // [1]
call方法实质上是调用Function.prototype.call方法,因此上面的表达式可以用bind方法改写
- var slice = Function.prototype.call.bind(Array.prototype.slice);
- slice([1, 2, 3], 0, 1); // [1]
- var slice = Function.prototype.call.bind(Array.prototype.slice);
- var push = Function.prototype.call.bind(Array.prototype.push);
- var pop = Function.prototype.call.bind(Array.prototype.pop);
- var a = [1 ,2 ,3];
- push(a, 4)
- a // [1, 2, 3, 4]
- pop(a)
- a // [1, 2, 3]
- var push = Function.prototype.call.bind(Array.prototype.push);
- [1, 2, 3].slice(0, 1); // [1]
- 如果再进一步,将 Function.prototype.call 方法绑定到 Function.prototype.bind 对象,就意味着 bind 的调用形式也可以被改写
- function f() {
- console.log(this.v);
- }
- var o = { v: 123 };
- var bind = Function.prototype.call.bind(Function.prototype.bind);
- bind(f, o)(); //
所以
bind
方法就可以直接使用,不需要在函数实例上使用- function f() {
- 利用bind方法,可以改写一些 JavaScript 原生方法的使用形式,以数组的slice方法为例
- 每一次返回一个新函数
- bind() 使用注意
(78)Wangdao.com第十五天_JavaScript 面向对象的更多相关文章
- (79)Wangdao.com第十五天_JavaScript 对象的继承_prototype原型对象_封装_函数式编程
javascript 内置了许多 function 函数(){...} js 执行首先就会执行自己内置的函数定义 (function Function.function Object) 对象的继承 大 ...
- (77)Wangdao.com第十五天_JavaScript 用于数据交换的文本格式 JSON 对象
JSON 对象 JSON (JavaScript Object Notation 的缩写) 也是一种数据,是 JavaScript 的原生对象,用来处理 JSON 格式数据.它有两个静态方法:JSON ...
- “全栈2019”Java第三十五章:面向对象
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- (76)Wangdao.com第十四天_JavaScript 正则表达式对象 RegExp
RegExp Regular Expression,正则表达式是一种表达 文本模式(字符串结构) 的式子. 常常用来按照“给定模式”匹配文本.比如,正则表达式给出一个 Email 地址的模式, ...
- (92)Wangdao.com_第二十五天_线程机制_H5 Web Workers 分线程任务_事件 Event
浏览器内核 支撑浏览器运行的最核心的程序 IE 浏览器内核 Trident内核,也是俗称的IE内核Chrome 浏览器内核 统称为 Chromium 内核或 ...
- 第十五节 JS面向对象实例及高级
实例:面向对象的选项卡 把面向过程的程序,改写成面向对象的形式 原则:不能有函数套函数,但可以有全局变量 过程: onload —— 改写成 构造函数,其中window.onload的功能是在页面加载 ...
- 学习python第十五天,面向对象
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的. 面向对象技术简介 类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了该集 ...
- java 面向对象(十五):面向对象的特征三:多态性
1.多态性的理解:可以理解为一个事物的多种形态.2.何为多态性:对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)举例:Person p = new Man();Object obj ...
- 无废话ExtJs 入门教程十五[员工信息表Demo:AddUser]
无废话ExtJs 入门教程十五[员工信息表Demo:AddUser] extjs技术交流,欢迎加群(201926085) 前面我们共介绍过10种表单组件,这些组件是我们在开发过程中最经常用到的,所以一 ...
随机推荐
- Docker:手动制作镜像 [五]
一.制作docker镜像的步骤 1.启动容器安装软件服务 2.将安装好服务的容器commit提交为镜像 3:.启动新容器来测试新提交的镜像 二.制作支持ssh远程登录的docker镜像 1.启动容器安 ...
- $L^p$ 调和函数恒为零
设 $u$ 是 $\bbR^n$ 上的调和函数, 且 $$\bex \sen{u}_{L^p}=\sex{\int_{\bbR^n}|u(y)|^p\rd y}^{1/p}<\infty. \e ...
- Mysql的跨服务器 关联查询--Federated引擎
1.确认开启Federated引擎 查询FEDERATED功能是否开启: show ENGINES; 2.如果状态为NO则需修改my.ini文件,增加一行federated配置: ...
- day 15 - 1 内置函数
内置函数 作用域相关 locals() globals() #这两组开始容易搞混 print(locals()) #返回本地作用域中的所有名字 print(globals()) #返回全局作用域中的所 ...
- Centos7 安装 tree
Centos7 安装 tree 用命令 yum 安装 tree yum -y install tree
- SSH之Hibernate总结篇
Hibernate hibernate 简介: hibernate是一个开源ORM(Object/Relationship Mipping)框架,它是对象关联关系映射的持久层框架,它对JDBC做了轻量 ...
- 【转】mac环境下Android 反编译
一.需要的工具 apktool:反编译APK文件,得到classes.dex文件,同时也能获取到资源文件以及布局文件. dex2jar:将反编译后的classes.dex文件转化为.jar文件. jd ...
- django反向解析传参
这两天写代码总是有反向解析传参顺带复习了一下反向解析,以下是简单的反向解析 以下是我最近写的很多的反向解析传参 想要实现点击修改将这些从数据库读取的内容传到另一个页面就要通过id来查询,那么我们就需 ...
- 【原创】大叔经验分享(19)spark on yarn提交任务之后执行进度总是10%
spark 2.1.1 系统中希望监控spark on yarn任务的执行进度,但是监控过程发现提交任务之后执行进度总是10%,直到执行成功或者失败,进度会突然变为100%,很神奇, 下面看spark ...
- 解决 Composer-Setup.exe 安装过程中的报错
问题 在 Windows 7 执行 Composer-Setup.exe 以安装 Composer 过程中 上图中点击[Next]时,出现如下报错信息 原因分析 由上述提示信息,可推测两方面原因: 1 ...