当前位置: 首页 > news >正文

JavaScript 对象操作、继承与模块化实现

1. Object 对象相关方法


Object.getPrototypeOf():返回参数对象的原型,是获取原型对象的标准方法。

var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype; // true

Object.setPrototypeOf():为参数对象设置原型,返回该参数对象。可用于模拟new命令。


var a = {};
var b = {x: 1};
Object.setPrototypeOf(a, b);
Object.getPrototypeOf(a) === b; // true

Object.create():以指定对象为原型,返回一个新的实例对象。还可接受第二个参数,用于添加实例自身的属性。


var A = { print: function () { console.log('hello'); } };
var B = Object.create(A);
B.print(); // hello

Object.prototype.isPrototypeOf():判断该对象是否为参数对象的原型,只要实例对象处在参数对象的原型链上,就返回true。


var o1 = {};
var o2 = Object.create(o1);
var o3 = Object.create(o2);
o2.isPrototypeOf(o3); // true

Object.prototype.__proto__:返回对象的原型,该属性可读写,但不建议使用,推荐用Object.getPrototypeOf()和Object.setPrototypeOf()。


var obj = {};
var p = {};
obj.__proto__ = p;
Object.getPrototypeOf(obj) === p; // true

Object.getOwnPropertyNames():返回一个数组,成员是参数对象本身的所有属性的键名,不包含继承的属性键名。


Object.getOwnPropertyNames(Date); 

Object.prototype.hasOwnProperty():判断某个属性定义在对象自身,还是定义在原型链上。


Date.hasOwnProperty('length'); // true

in运算符:返回一个布尔值,表示一个对象是否具有某个属性,不区分该属性是对象自身的还是继承的。


'length' in Date; // true

for...in循环:用于遍历对象的所有可遍历属性(包括自身和继承的)。


var o1 = { p1: 123 };
var o2 = Object.create(o1, { p2: { value: "abc", enumerable: true } });
for (p in o2) { console.info(p); }


2. 对象的继承


原型对象概述
构造函数的缺点:同一个构造函数的多个实例之间,无法共享属性,造成系统资源浪费。


function Cat(name, color) {
this.name = name;
this.color = color;
this.miaomiao = function () { console.log('喵喵'); };
}
var cat1 = new Cat('大毛', '白色');
var cat2 = new Cat('二毛', '黑色');
cat1.meow === cat2.meow; // false

prototype属性的作用:原型对象的所有属性和方法,都能被实例对象共享。


function Animal(name) { this.name = name; }
Animal.prototype.color = 'white';
var cat1 = new Animal('大毛');
var cat2 = new Animal('二毛');
cat1.color; // 'white'

原型链:所有对象都有自己的原型对象,形成一个 “原型链”,最终都可以上溯到Object.prototype,其原型是null。


Object.getPrototypeOf(Object.prototype); // null

constructor属性:prototype对象的constructor属性默认指向prototype对象所在的构造函数,可用于得知实例对象的构造函数。修改原型对象时,一般要同时修改constructor属性。


function P() {}
P.prototype.constructor === P; // true


instanceof运算符
返回一个布尔值,表示对象是否为某个构造函数的实例,其实质是检查右边构造函数的原型对象是否在左边对象的原型链上。

var v = new Vehicle();
v instanceof Vehicle; // true


构造函数的继承
分两步实现:

在子类的构造函数中,调用父类的构造函数。


function Sub(value) {
Super.call(this);
this.prop = value;
}

让子类的原型指向父类的原型。


Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;


多重继承
JavaScript 不提供多重继承功能,但可通过变通方法实现,如 Mixin 模式。


function M1() { this.hello = 'hello'; }
function M2() { this.world = 'world'; }
function S() {
M1.call(this);
M2.call(this);
}
S.prototype = Object.create(M1.prototype);
Object.assign(S.prototype, M2.prototype);
S.prototype.constructor = S;


3. 模块化编程
基本的实现方法
把模块写成一个对象,所有的模块成员都放到这个对象里面,但会暴露所有模块成员。


var module1 = new Object({
_count : 0,
m1 : function (){ /*...*/ },
m2 : function (){ /*...*/ }
});


封装私有变量
构造函数的写法:将私有变量封装在构造函数中,但会导致构造函数与实例对象一体,耗费内存。


function StringBuilder() {
var buffer = [];
this.add = function (str) { buffer.push(str); };
this.toString = function () { return buffer.join(''); };
}

立即执行函数的写法:将相关的属性和方法封装在一个函数作用域里面,可达到不暴露私有成员的目的。


var module1 = (function () {
var _count = 0;
var m1 = function () { /*...*/ };
var m2 = function () { /*...*/ };
return { m1 : m1, m2 : m2 };
})();


模块的放大模式和宽放大模式


放大模式:为模块添加新方法。


var module1 = (function (mod){
mod.m3 = function () { /*...*/ };
return mod;
})(module1);

宽放大模式:适用于无法确定模块加载顺序的情况。


var module1 = (function (mod) { /*...*/ })(window.module1 || {});

输入全局变量
为保证模块的独立性,显式地将其他变量输入模块。

javascript
var module1 = (function ($, YAHOO) { /*...*/ })(jQuery, YAHOO);

http://www.xdnf.cn/news/1157023.html

相关文章:

  • RCE随笔(1)
  • 使用 Pyecharts 绘制精美饼状图:从基础到高级技巧
  • 【LeetCode 热题 100】236. 二叉树的最近公共祖先——DFS
  • Effective Python 条款13:通过带星号的unpacking操作来捕获多个元素,不要用切片
  • 构建一个简单的Java框架来测量并发执行任务的时间
  • 深入浅出理解动态规划
  • The FastMCP Client
  • `tidyverse` 中涉及的函数及其用法
  • 【RAG Agent】Deep Searcher实现逻辑解析
  • 【JS逆向基础】数据库之redis
  • 第一章: 初识 Redis:背后的特性和典型应用场景
  • 什么是 ELK/Grafana
  • 使用pytorch创建模型时,nn.BatchNorm1d(128)的作用是什么?
  • Muduo库中单例模式详解
  • Mysql(事务)
  • 小型支付项目3-5:检测未接收到或未正确处理的支付回调通知
  • UE5多人MOBA+GAS 番外篇:移植Lyra的伤害特效(没用GameplayCue,因为我失败了┭┮﹏┭┮)
  • 音视频学习(四十一):H264帧内压缩技术
  • 【Vue进阶学习笔记】Vue 路由入门指南
  • 单线程 Reactor 模式
  • 动静态库的制作和原理
  • 【unitrix】 6.10 类型转换(from.rs)
  • [BUG]关于UE5.6编译时出现“Microsoft.MakeFile.Targets(44,5): Error MSB3073”问题的解决
  • 【软件测试】从软件测试到Bug评审:生命周期与管理技巧
  • VUE2 学习笔记2 数据绑定、数据代理、MVVM
  • 【数据结构】第一讲 —— 概论
  • 基于Arduino的智能寻迹小车设计
  • 剑指offer——链表:旋转数组的最小数字
  • 【OD机试】池化资源共享
  • 「Java案例」利用方法求反素数