function Fn() {/*1.要有一个对象// 方案1let obj = {}obj.__proto__ = FC.prototype// 方案2let obj = ate(FC.prototype)2.执行此函数,解决this的指向 let ret = FC.apply(obj)3.判断函数执行的返回值,是基本类型或无返回值则返回对象,有引用类型,则返回指定的*/
}
let f1 = new Fn()// ===============================================================
function _new(Construct, ...args) {// 创建一个实例对象(创建Construct类的实例,让其 对象.__proto__ = Construct.prototype)// obj.__proto__ = Construct.prototypelet obj = ate(Construct.prototype)// 把函数执行,让this指向实例对象let ret = Construct.call(obj, ...args)// 处理返回值,引用类型,直接返回引用类型的值if (ret !== null && /^(object|function)$/.test(typeof ret)) {return ret}return obj
}function Fn(name) {this.name = namethis.age = function () {console.log('方法===' + this.name)}
}
let f1 = _new(Fn, '张三')
f1.age()
Call = function (ctx, ...params) {// 参数可以为 undefined或nullctx = ctx == null ? window : ctx// 需要保证ctx必须是对象类型的值:因为只有对象才能设置属性ctx = !/^(object|function)$/.test(typeof ctx) ? Object(ctx) : ctxlet self = thislet ret = null// 新增的属性名保证唯一性,防止污染原始对象中的成员数据let functionName = Symbol('functionName')// 给对象添加属性ctx[functionName] = self// 执行方法ret = ctx[functionName](...params)// 删除自定义属性delete ctx[functionName]return ret
};function fn(x, y) {console.log(this, x, y)
}
let obj = {name: '张三'
}
fn.myCall(obj, 2, 3)
function fn1(a, b, c, ...d) {console.log(this, a, b, c, d)return '你的姓名为:' + this.name};var obj = { name: 2222, fn: 'abc' };// 自定义一个apply方法,强制改变this指向Apply = function (Ctx, args) {if (!Array.isArray(args)) throw new TypeError('参数2必须是数组');// == 为null,判断是否为 null或undefined// console.log(Ctx == null)Ctx = Ctx == null ? window : (typeof Ctx != 'object' ? Object(Ctx) : Ctx)// 给传入的对象添加一个属性// 给自定义的属性添加一个随机名称const methodName = Symbol();// Ctx.fn = thisCtx[methodName] = this// 执行// let ret = Ctx.fn()let ret = Ctx[methodName](...args)// 删除delete Ctx[methodName]// 返回return ret;}
Bind = function myBind(ctx, ...params) {let self = thisreturn function (...args) {self.apply(ctx, [...params, ...args])}
};var obj = { id: 1 }
function fn(...args) {console.log(this, args)
}
lick = fn.bind(obj, 1, 2)
检测构造函数的prototype是否出现在实例的__proto__上
构造函数 Symbol.hasInstance属性
function _instanceof(obj, FC) {// 如果不是对象则抛异常if (typeof obj !== 'object') throw new TypeError('必须是引用类型!');// 对象不能是函数if (typeof obj === "function") return false;// obj为null 或 undefined 为 falseif (obj == null) return false;// 得到当前FC原型var prototype = FC.prototype;if (!prototype) return false;// 兼容性判断处理 环境支持es6 ==> typeof Symbol 暂时性死区,es6的判断if (typeof Symbol === "function") {// 返回true/falsevar insFn = FC[Symbol.hasInstance];if (typeof insFn === "function") { // 可以被调用执行return insFn.call(FC, obj) }}// 得到对象的原型 --- 针对于老版本浏览器,es5的判断// var proto = obj.__proto__var proto = PrototypeOf(obj)//console.log(proto.__proto__) return falsewhile (1) {if (proto === null) return false;if (proto === prototype) return true;// proto = proto.__proto__proto = PrototypeOf(proto)}}
ES5 提供了 Object.defineProperty 方法,该方法可以在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。Object.defineProperty无法监听数组变化。
var obj = {test:"hello"
}
//对象已有的属性添加特性描述
Object.defineProperty(obj,"test",{// 能不能被配置(删除)
configurable:true | false,
// 是否可枚举enumerable:true | false,
value:任意类型的值,
// 是否可写,此配置和 get/set不能同时存在
writable:true | false,
get(){},
set(value){}
});// ===============================================
var data = {name: '张三'
}function observer(data) {if (typeof data !== 'object') return datafor (let key in data) {defineReactive(data, key, data[key])}
}function defineReactive(target, key, value) {observer(value)Object.defineProperty(target, key, {get() {return value},set(newVal) {if (value !== newVal) {value = newValupdate(key, value)}}})
}function update(key, value) {document.querySelectorAll(`[v-bind="${key}"]`).forEach(el => {if (el.tagName === 'INPUT') {el.value = value} else {el.innerHTML = value}})
};
// 监听
observer(data);// 初始化
document.querySelectorAll('[v-model]').forEach(el => {el.addEventListener('keyup', function () {let prop = Attribute('v-model')data[prop] = this.value})
})
Proxy是es6提供的新的api,Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
(1)Proxy可以直接监听对象而非属性
(2)Proxy直接可以劫持整个对象,并返回一个新对象,不管是操作便利程度还是底层功能上都远强于Object.defineProperty。
(3)Proxy可以直接监听数组的变化
(4)Proxy有多达13种拦截方法,不限于apply、ownKeys、deleteProperty、has等等是Object.defineProperty不具备的。
const obj = { name: "张三" };const proxy = new Proxy(obj, {get(target, key) {return target[key];},set(target, key, value) {console.log(target, key, value)target[key] = value;return true;}
});
proxy.age = 10;
console.log(proxy, obj);
const news = [{title: "海外网深一度:气候危机“逼近灾难临界值”,中国行动振奋世界"},{title: "小区不准外卖员入内,杭州一外卖小哥回家被保安拦下!民警到场调解,小哥情绪崩溃"},{title: "网传浙江慈溪上林中学一女生教室内被多次扇耳光 当地回应:已去处置"}
];
const newsProxy = new Proxy(news, {get(target, key) {let title = target[key]['title'];target[key]['title'] = title.length > 10 ? title.substr(0, 10) + '...' : titlereturn target[key]}
});console.log(newsProxy[0])
let obj = {name: '张三',
}const proxyHandler = {get(target, key) {if (typeof target[key] === "object") {return new Proxy(target[key], proxyHandler)}return target[key]},set(target, key, value) {let oldValue = target[key]if (oldValue !== value) {target[key] = valueupdate(key, value)return true}}
}let proxy = new Proxy(obj, proxyHandler)function update(key, value) {document.querySelectorAll(`[v-bind="${key}"]`).forEach(el => {if (el.tagName === 'INPUT') {el.value = value} else {el.innerHTML = value}})
}// 初始化时
document.querySelectorAll('[v-model]').forEach(el => {el.addEventListener('keyup', function () {let prop = Attribute('v-model')proxy[prop] = this.value})
})
本文发布于:2024-01-30 15:39:21,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170660036621052.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |