/**
* js中的new()到底做了些什么?
* 1,创建一个新对象
* 2,将构造函数里面的作用域赋值给新对象(因为this指向了新对象)
* 3,执行构造函数里面代码
* 4,返回新对象
*/
function
Base() {
this.
name =
'xiaoming';
}
var
obj =
new
Base();
/**
* 解释上面的
*/
var
obj
obj.
_proto_ =
Base.
prototype;
Base.
call(
obj);
/**
* constructor:每个实例对象所拥有的属性,的值返回创建此对象的函数数组的引用,
* instanceof:用来检测这个实例是不是有这类创建的(new出来的)
*/
function
A() { };
var
a =
new
A();
alert(
a
instanceof
A);
// true
// 用来检测当前对象的_proto_属性是否指向了创建它的对象的prototype所指向的那块内存
function
A() { };
var
a =
new
A();
a.
__proto__
alert(
a
instanceof
A);
// false
/**
* Object.creat(proto [, propertiesObject ])
* 有二个属性,第一个属性继承了原型的属性,第二个参数是对象属性的描述
*/
// 获取Array原型
const
arrayProto =
Array.
prototype;
const
arrayMethods =
Object.
create(
arrayProto);
const
newArrProto
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
forEach(
method
=>
// 原生Array的原型方法
let
original =
arrayMethods[
method];
// 将push,pop等方法重新封装并定义在对象newArrProto的属性上
// 这里需要注意的是封装好的方法是定义在newArrProto的属性上而不是其原型属性
// newArrProto.__proto__ 没有改变
newArrProto[
method] =
function
console.
log(
'监听到数组的变化啦!');
// 调用对应的原生方法并返回结果(新数组长度)
return
original.
apply(
this,
arguments);
}
});
let
list = [
1,
2];
// 将我们要监听的数组的原型指针指向上面定义的空数组对象
// newArrProto的属性上定义了我们封装好的push,pop等方法
list.
__proto__ =
newArrProto;
list.
push(
3);
// 监听到数组的变化啦! 3
/**
* 使用es6的模式继承 监听变化
*/
class
NewArray
extends
Array
constructor(...
args) {
// 调用父类Array的constructor()
super(...
args)
}
push(...
args) {
console.
log(
'监听到数组的变化啦!');
// 调用父类原型push方法
return
super.
push(...
args)
}
// ...
}
let
list3 = [
1,
2];
let
arr =
new
NewArray(...
list3);
console.
log(
arr)
// (2) [1, 2]
arr.
push(
3);
// 监听到数组的变化啦!
console.
log(
arr)
// (3) [1, 2, 3]
/**
* 寄生式继承
*/
function
inheritObject(
o) {
// 声明一个过渡函数
function
F() { }
// 过渡对象的原型继承父对象
F.
prototype =
o;
return
new
F();
}
function
inheritPrototype(
subClass,
superClass) {
//复制一份父类的原型副本保存到变量中
var
p =
inheritObject(
superClass.
prototype)
// 重写了子类的原型,防止constructor指向父类
p.
constructor =
subClass;
// 设置子类的原型
subClass.
prototype =
p;
}
function
ArrayOfMine(
args) {
Array.
apply(
this,
args);
}
inheritPrototype(
ArrayOfMine,
Array);
// 重写父类Array的push,pop等方法
ArrayOfMine.
prototype.
push =
function
console.
log(
'监听到数组的变化啦!');
return
Array.
prototype.
push.
apply(
this,
arguments);
}
var
list4 = [
1,
2];
var
newList =
new
ArrayOfMine(
list4);
console.
log(
newList,
newList.
length,
newList
instanceof
Array,
Array.
isArray(
newList));
// ArrayOfMine {} 0 true false
newList.
push(
3);
console.
log(
newList,
newList.
length,
newList
instanceof
Array,
Array.
isArray(
newList));
// ArrayOfMine [3]0: 3length: 1__proto__: Array 1 true false
/**
* 为什么将父类改成Array就行不通了呢?因为Array构造函数执行时不会对传进去的this做任何处理。
*
*/
function
inheritObject(
o) {
function
F() { };
F.
prototype =
o;
return
new
F();
}
function
inheritPrototype(
subClass,
superClass) {
var
p =
inheritObject(
superClass.
prototype);
p.
constructor =
subClass;
subClass.
prototype =
p;
}
function
Father() {
// 这里我们暂且就先假定参数只有一个
this.
args =
arguments[
0];
return
this.
args;
}
Father.
prototype.
push =
function
this.
args.
push(
arguments);
console.
log(
'我是父类方法');
}
function
ArrayOfMine() {
Father.
apply(
this,
arguments);
}
inheritPrototype(
ArrayOfMine,
Father);
// 重写父类Array的push,pop等方法
ArrayOfMine.
prototype.
push =
function
console.
log(
'监听到数组的变化啦!');
return
Father.
prototype.
push.
apply(
this,
arguments);
}
var
list4 = [
1,
2];
var
newList =
new
ArrayOfMine(
list4,
3);
console.
log(
newList,
newList
instanceof
Father);
newList.
push(
3);
console.
log(
newList,
newList
instanceof
Father);
/**
* 最终监听数组的总结
*/
function
def(
obj,
key,
val,
enumerable) {
Object.
defineProperty(
obj,
key, {
value:
val,
enumerable: !!
enumerable,
configurable:
true,
writable:
true
})
}
// observe array
let
arrayProto =
Array.
prototype;
let
arrayMethods =
Object.
create(
arrayProto);
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
forEach(
method
=>
// 原始数组操作方法
let
original =
arrayMethods[
method];
def(
arrayMethods,
method,
function
let
arguments$1 =
arguments;
let
i =
arguments.
length;
let
args =
new
Array(
i);
while (
i--) {
args[
i] =
arguments$1[
i]
}
// 执行数组方法
let
result =
original.
apply(
this,
args);
// 因 arrayMethods 是为了作为 Observer 中的 value 的原型或者直接作为属性,所以此处的 this 一般就是指向 Observer 中的 value
// 当然,还需要修改 Observer,使得其中的 value 有一个指向 Observer 自身的属性,__ob__,以此将两者关联起来
let
ob =
this.
__ob__;
// 存放新增数组元素
let
inserted;
// 为add 进arry中的元素进行observe
switch (
method) {
case
'push':
inserted =
args;
break;
case
'unshift':
inserted =
args;
break;
case
'splice':
// 第三个参数开始才是新增元素
inserted =
args.
slice(
2);
break;
}
if (
inserted) {
ob.
observeArray(
inserted);
}
// 通知数组变化
ob.
dep.
notify();
// 返回新数组长度
return
result;
})
})
pasting
http://www.51xuediannao.com/javascript/javascriptjtszbh_1258.html
js监听resize变化只执行最后一次 js监听值变化
转载文章标签 js监听resize变化只执行最后一次 前端 javascript ViewUI 数组 文章分类 架构 后端开发
-
java 监听 sqlserver 数据库的变化
java 监听 sqlserver 数据库的变化
Server SQL Java -
js监听变量的变化
/监听a对象的age属性var a = { age: 10 };Object.defineProperty(a, 'age', { get: function() { //
javascript 前端 es6 html 默认值