JS对象模型

深入浅出JavaScript对象模型 JavaScript中的对象 ECMA262规范一直在强调,“ECMAScript是一种基于对象(Object—Based)的语言,而不是传统的面向对象(Object—Oriented)的语言”。相信绝大多数人不会清楚这句话是什么意思。我想我们可以把它简化一下:你可以把对象看做是存放数据的大的数组,每个对象都有一个属于自己的属性列表,里面存放了对象的所有的attributes和methods 立即下载


JavaScript 是一种基于原型(Prototype)的面向对象语言,而不是基于类的面向对象语言

C++、Java有类Class和实例Instance的概念,类是一类事物的抽象,而实例则是类的实体

JS是基于原型的语言,它只有原型对象的概念。原型对象就是一个模板,新的对象从这个模板构建从而获取最初的属性。任何对象在运行时可以动态的增加属性。而且,任何一个对象都可以作为另一个对象的原型,这样后者就可以共享前者的属性

定义类

字面式声明方式

var obj = {
    property_1: value_1, // property_# may be an identifier...  
    property_2: value_2, // or a number...
    ...,
    "property n": value_n // or a string
};

var obj = {
    x: 1,
    1: 'abc',
    'y': '123'
}
for (let s in obj)
    console.log(s, typeof (s));

这种方法也称作字面值创建对象
Js 1.2开始支持

let a = 1, b = 2
let obj = { a, b }
let obj1 = { a: a, 'b': b } // 引号可以省

console.log(obj) // { a: 1, b: 2 }
console.log(obj1) // { a: 1, b: 2 }
let c = 'pro1'
let d = {
    c: 1000, // 注意这个c是'c',不是上面的变量c
    [c]: 2000 // 如果要用c变量,就要把c用中括号括起来
}

对象的键key只能是字符串类型,最后都会被转换成字符串

ES6之前——构造器

1、定义一个函数(构造器)对象,函数名首字母大写
2、使用this定义属性
3、使用new和构造器创建一个新对象

// 定义类,构造器
function Point(x, y) {
    this.x = x;
    this.y = y;
    this.show = () => { console.log(this, this.x, this.y) };
    console.log('Point~~~~~~~~');
}

console.log(Point);
p1 = new Point(4, 5);
console.log(p1);
console.log('----------------');
// 继承
function Point3D(x, y, z) {
    Point.call(this, x, y); // "继承"    
    this.z = z;
    console.log('Point3D~~~~~~~~');
}

console.log(Point3D);
p2 = new Point3D(14, 15, 16);
console.log(p2);
p2.show();

/* 执行结果
[Function: Point]
Point~~~~~~~~
Point { x: 4, y: 5, show: [Function] }
----------------
[Function: Point3D]
Point~~~~~~~~
Point3D~~~~~~~~
Point3D { x: 14, y: 15, show: [Function], z: 16 }
Point3D { x: 14, y: 15, show: [Function], z: 16 } 14 15
*/

new 构建一个新的通用对象,new操作符会将新对象的this值传递给Point3D构造器函数,函数为这个对象创建z属性。
从上句话知道,new后得到一个对象,使用这个对象的this来调用构造器,那么如何执行“基类”的构造器方法呢?
使用Point3D对象的this来执行Point的构造器,所以使用call方法,传入子类的this。
最终,构造完成后,将对象赋给p2。

注意:如果不使用new关键字,就是一次普通的函数调用,this不代表实例。

ES6中的class

从ES6开始,新提供了class关键字,使得创建对象更加简单、清晰

  1. 类定义使用class关键字。创建的本质上还是函数,是一个特殊的函数
  2. 一个类只能拥有一个名为constructor的构造器方法。如果没有显式的定义一个构造方法,则会添加一个默认的constuctor方法
  3. 继承使用extends关键字
  4. 一个构造器可以使用super关键字来调用一个父类的构造函数
  5. 类没有私有属性
// 基类定义
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
    }
    show() /*方法*/ {
        console.log(this, this.x, this.y);
    }
}

let p1 = new Point(10, 11)
p1.show()
// 继承
class Point3D extends Point {
    constructor(x, y, z) {
        super(x, y);
        this.z = z;
    }
}

let p2 = new Point3D(20, 21, 22);
p2.show()

/* 执行结果
Point { x: 10, y: 11 } 10 11
Point3D { x: 20, y: 21, z: 22 } 20 21
*/

重写方法

子类Point3D的show方法,需要重写

// 基类定义
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
    }
    show() /*方法*/ {
        console.log(this, this.x, this.y);
    }
}

let p1 = new Point(10, 11)
p1.show()

// 继承
class Point3D extends Point {
    constructor(x, y, z) {
        super(x, y);
        this.z = z;
    }

    show() { // 重写
        console.log(this, this.x, this.y, this.z);
    }
}

let p2 = new Point3D(20, 21, 22);
p2.show();

/* 执行结果
Point { x: 10, y: 11 } 10 11
Point3D { x: 20, y: 21, z: 22 } 20 21 22
*/

子类中直接重写父类的方法即可
如果需要使用父类的方法,使用super.method()的 方式调用

  • 使用箭头函数重写上面的方法
// 基类定义
// 基类定义
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
        //this.show = function () {console.log(this,this.x,this.y)};
        this.show = () => console.log('Point');
    }
}

// 继承
class Point3D extends Point {
    constructor(x, y, z) {
        super(x, y);
        this.z = z;
        this.show = () => console.log('Point3D');
    }
}

let p2 = new Point3D(20, 21, 22);
p2.show(); // Point3D

从运行结果来看,箭头函数也支持子类的覆盖

// 基类定义
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
        this.show = () => console.log('Point');
    }
    // show() /*方法*/ {     
    // console.log(this,this.x,this.y);     
    // }
}

// 继承
class Point3D extends Point {
    constructor(x, y, z) {
        super(x, y);
        this.z = z;
        //this.show = () => console.log('Point3D');
    }
    show() { // 重写
        console.log('Point3D');
    }
}

let p2 = new Point3D(20, 21, 22);
p2.show(); // Point

上例优先使用了父类的属性show

// 基类定义
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
        //this.show = () => console.log('Point');
    }
    show() /*方法*/ {
        console.log(this, this.x, this.y);
    }
}

// 继承
class Point3D extends Point {
    constructor(x, y, z) {
        super(x, y);
        this.z = z;
        this.show = () => console.log('Point3D');
    }
}

let p2 = new Point3D(20, 21, 22);
p2.show(); // Point3D

优先使用了子类的属性

总结

  • 父类、子类使用同一种方式类定义属性或者方法,子类覆盖父类
  • 访问同名属性或方法时,优先使用属性

静态属性

静态属性目前还没有得到很好的支持

静态方法

在方法名前加上static,就是静态方法

class Add {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    static print() {
        console.log(this.x); // ? this是什么
    }
}

add = new Add(40, 50);
console.log(Add);
Add.print();
//add.print(); // 实例不能访问直接访问静态方法,和C++、Java一致
add.constructor.print(); // 实例可以通过constructor访问静态方法

/* 执行结果
[Function: Add]
undefined
undefined
*/

静态方法中的this是Add类,而不是Add的实例

  • 注意:
    静态的概念和Python的静态不同,相当于Python中的类变量

this的坑

虽然Js和 C++ 、Java一样有this,但是Js的表现是不同的。
原因在于, C++ 、Java是静态编译型语言,this是编译期绑定,而Js是动态语言,运行期绑定

var school = {
    name: 'js',
    getNameFunc: function () {
        console.log(this.name);
        console.log(this);
        return function () {
            console.log(this === global); // this是否是global对象    
            return this.name;
        };
    }
};

console.log(school.getNameFunc()());

/* 运行结果
js
{ name: 'js', getNameFunc: [Function: getNameFunc] }
true
undefined
*/

函数执行时,会开启新的执行上下文环境ExecutionContext

创建this属性,但是this是什么就要看函数是怎么调用的了

  1. myFunction(1,2,3),普通函数调用方式,this指向全局对象。全局对象是nodejs的global或者浏览器中的windows
  2. myObject.myFunction(1,2,3),对象方法的调用方式,this指向包含该方法的对象
  3. call、apply、bind方法调用时,要看第一个参数是谁

分析上例

  • js 和 { name: 'js', getNameFunc: [Function: getNameFunc] } 很好理解
  • 第三行打印的true,是 console.log(this == global) 执行的结果,说明当前是global,因为调用这个返回的函数是直接调用的,这就是个普通函数调用,所以this是全局对象
  • 第四行undefined,就是因为this是global,没有name属性

这就是函数调用的时候,调用方式不同,this对应的对象不同,它已经不是C++、Java的指向实例本身了
this的问题,这是历史遗留问题,新版只能保留且兼容了
而我们在使用时,有时候需要明确的让this必须是我们期望的对象,如何解决这个问题呢?

1 显式传入

var school = {
    name: 'js',
    getNameFunc: function () {
        console.log(this.name);
        console.log(this);
        return function (that) {
            console.log(this == global); // this是否是global对象    
            return that.name;
        };
    }
}
console.log(school.getNameFunc()(school));

    /* 运行结果
js
{ name: 'js', getNameFunc: [Function: getNameFunc] }
true
js
*/

通过主动传入对象,这样就避开了this的问题

2、 ES3(ES-262第三版)引入了apply、call方法

var school = {
    name : 'js',   
    getNameFunc : function () {   
    console.log(this.name);   
    console.log(this);   
    return function () {    
    console.log(this == global); // this是否是global对象    
    return this.name;
     };
     }
    }
    console.log(school.getNameFunc().call(school)); // call方法显式传入this对应的对象

/* 运行结果
js
{ name: 'js', getNameFunc: [Function: getNameFunc] }
false
js
*/

apply、call方法都是函数对象的方法,第一参数都是传入对象引入的
apply传其他参数需要使用数组
call传其他参数需要使用可变参数收集

function Point(x, y) {
    this.x = x;
    this.y = y;
    console.log(this === global);
    console.log('Point ~~~~');
}

p1 = Point(4, 5);
console.log(p1); // undefined

console.log('~~~~~~~~~~~~~~~~')

p2 = new Object();
console.log(p2); // {}

p3 = Point.call(p2, 10, 11);
// p3 = Point.apply(p2, [11, 13]);
console.log(p3); // undefined
console.log(p2); // { x: 10, y: 11 }

/* 执行结果
true
Point ~~~~
undefined
~~~~~~~~~~~~~~~~
{}
false
Point ~~~~
undefined
{ x: 10, y: 11 }
*/

3、ES5 引入了bind方法

bind方法来设置函数的this值

var school = {
    name: 'js',
    getNameFunc: function () {
        console.log(this.name); // 
        console.log(this); 
        return function () {
            console.log(this == global); // this是否是global对象   
            return this.name;
        };
    }
}

console.log(school.getNameFunc().bind(school)); // bind方法绑定

/* 执行结果
js
{ name: 'js', getNameFunc: [Function: getNameFunc] }
[Function: bound ]
*/

只打印了三行,说明哪里有问题,问题出在bind方法用错了

var school = {
    name: 'js',
    getNameFunc: function () {
        console.log(this.name); // 
        console.log(this); 
        return function () {
            console.log(this == global); // this是否是global对象   
            return this.name;
        };
    }
}

var func = school.getNameFunc();
console.log(func);

var boundfunc = func.bind(school); // bind绑定后返回新的函数
console.log(boundfunc);
console.log(boundfunc());


/* 执行结果
js
{ name: 'js', getNameFunc: [Function: getNameFunc] }
[Function]
[Function: bound ]
false
js
*/

apply、call方法,参数不同,调用时传入this
bind方法是为函数先绑定this,调用时直接用

4、ES6引入支持this的箭头函数

ES6 新技术,就不需要兼容this问题

var school = {
    name: 'js',
    getNameFunc: function () {
        console.log(this.name);
        console.log(this);
        return () => {
            console.log(this == global); // this是否是global对象
            return this.name;
        };
    }
}
console.log(school.getNameFunc()());

/* 运行结果
js
{ name: 'js', getNameFunc: [Function: getNameFunc] }
false
js
 */
  • ES6 新的定义方式如下
class school {
    constructor() {
        this.name = 'js';
    }
    getNameFunc() {
        console.log(this.name);
        console.log(this, typeof (this));
        return () => {
            console.log(this == global); // this是否是global对象    
            return this.name;
        };
    }
}
console.log(new school().getNameFunc()());

/* 执行结果
js
school { name: 'js' } 'object'
false
js
*/

以上解决this问题的方法,bind方法最常用

JavaScript对象模型 立即下载

相关推荐

光电容积脉搏波PPG信号分析笔记

脉搏波信号PPG分析笔记

teresa_zp的专栏 6476

JS中的对象模型——DOM、BOM

DOM和BOM是Web开发中的两个重要模型 Javascript可以通过DOM定位指定的元素,属性,进而实现查找、修改、创建等操作

qq_62225979的博客 510

Vivado与VCS+Verdi联合仿真环境搭建全攻略

本文详细介绍了如何搭建Vivado与VCS+Verdi联合仿真环境,旨在解决Vivado Simulator在大型FPGA验证中速度慢、调试弱的问题。通过指导工具版本配对、环境变量设置、关键参数配置及Xilinx仿真库编译,帮助工程师高效整合Vivado的设计管理、VCS的高速仿真与Verdi的深度调试能力,从而显著提升验证效率。

weixin_29219189的博客 576

JS中的对象模型

JS中的对象模型1、JS中的对象模型1.1 window对象1.2 定时器1.3 document对象1.4 document 对象查询节点1.5 document对象中的增加节点1.6 document中的删除节点1.7 关于Select和Option对象 1、JS中的对象模型 (1)BOM:浏览器对象模型 Browser Object Model,用来访问和操纵浏览器窗口 具体通过window对象来实现浏览器窗口的操纵。 (2)DOM:文档对象模型 Document Object Model,用来操纵

gezongbo的博客 1027

Maven的下载安装配置教程(详细图文)

目录 一、简单了解一下什么是Maven 二、maven的下载 三、maven的安装 四、maven的环境变量配置 五、setting文件配置 六、开发工具配置Maven 一、简单了解一下什么是Maven Maven就是一款帮助程序员构建项目的工具,我们只需要告诉Maven需要哪些Jar 包,它会帮助我们下载所有的Jar,极大提升开发效率。 1.Maven翻译为“专家“, ”内行”的意思,是著名Apache公司下基于Java开发的开源项目。 2.Maven项目对象模型(POM)是一..

bakelFF的博客 12万+

Rocky Linux 9 离线环境Docker部署实战:从依赖打包到服务启动

本文提供了一份详尽的Rocky Linux 9离线环境Docker部署实战指南。针对无法访问外网的生产或内网服务器,文章详细讲解了如何在联网跳板机上下载Docker二进制包及所有系统依赖RPM包,并完成打包。随后,手把手指导在离线服务器上进行依赖安装、二进制文件部署、systemd服务配置、SELinux与防火墙调优,最终实现Docker服务的成功启动与验证。

weixin_28363123的博客 138

JavaScript 的“世界模型”:深入理解对象 (Objects)

在 JavaScript 中,对象是一种复合数据类型,它允许我们将多个键值对 (key-value pairs) 组合在一起,用来描述一个实体(比如一个人、一辆车、一个订单)的特征和行为。这些是更现代、更推荐的方法,它们只关注对象自身的可枚举属性,并返回数组,可以方便地配合数组方法(如 forEach​)或 for...of​ 循环使用。对象的属性值不仅可以是数据,还可以是函数!这种方式更灵活,方括号 []​ 里面放的是一个字符串(或者能计算出字符串的表达式,比如变量),这个字符串就是你要访问的属性名。

wozhenbang2的博客 1849

【STK】手把手教你利用STK进行导弹和反导仿真01 - STK/MMT模块安装部署

【STK】手把手教你利用STK进行导弹和反导仿真01 - STK/MMT模块安装部署MMT模块与STK的版本是一一对应的,比如我现在手上的版本是MMT9的,那么我使用的STK的版本也必须是9版本的,如果你现在正在使用的是更高版本的STK,比如说10、11.2、11.6、12.2,那么该怎么办呢?这个经本人尝试,目前是可以多个STK版本共存的,我们可以根据自己的需要安装多个版本的STK下面开始讲解具体的安装步骤,

weixin_44184852的博客 2918

Js对象模型

JS对象模型 JavaScript是一种基于原型(Prototype)的面向对象语言,而不是基于类的面向对象语言. C++ Java有类Class和实例instance的概念,类是一类事物的抽象,而实例则是类的实体 Js是基于原型的语言,它只有原型对象的概念,原型对象就是一个模板,新的对象从这个模板构建从而获取最初的属性.任何对象在运行时可以动态的增加属性.而且,任何一个对象都可以作为另一个对象的...

刘振的博客 636

FPGA实现的AES加解密算法——Verilog源代码详解

本文将介绍基于FPGA的AES加解密算法的Verilog实现,并提供相应的源代码。根据密钥长度的不同,AES算法分为AES-128、AES-192和AES-256三种模式。对于已知的明文-密钥组合,可以使用在线的AES加解密工具计算出正确的密文,然后将该密文与FPGA加速器的输出进行比较。本文以AES-128算法为例,介绍基于FPGA的AES加解密算法的设计思路和Verilog实现。以上是基于FPGA的AES加解密算法的Verilog实现的相关内容。模块接受输入的明文和密钥,并输出加密后的密文。

HackSquad的博客 1976

通用、可复用的 AI Skill 开发基本流程

-----name:唯一标识符(建议用领域-功能格式):自然语言描述触发条件(AI 依赖此判断是否激活)tags(可选):便于分类和搜索version:支持后续迭代步骤输出物1. 定范围触发场景描述2. 写元数据name3. 填内容结构化 Markdown 文件4. 做验证可运行 + 符合规范5. 去集成放入对应 IDE 目录6. 持续维护跟进框架更新通过这套流程,你不仅可以开发(Hooks 最佳实践)(原生 WebGL 优化)(Pandas/Numpy 高效写法)

lpfasd123的博客 721

javascript对象模型

javascript对象模型 文章目录javascript对象模型定义类1.字面式声明方式(也称为字面值创建对象。)2.ES6之前----构造器构造类3.ES6中的class关键字this的不同作用域高阶对象、高阶类、或称Mixin模式继承实现高阶对象实现 JavaScript是一种基于原型(Prototype)的面向对象语言,而不是基于类的面向对象语言。 C++、Java有类Class和实例In...

兰枫 967

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【JavaScript】JS中的浏览器对象模型BOM

介绍【Javascript】中浏览器对象模型BOM的相关知识点,主要包括页面加载事件、两种定时器、JS执行机制

一文不值的博客 250

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

SharePoint之JavaScript客户端对象模型

最近一年以来,断断续续的做SharePoint的项目,主要是使用JavaScript进行开发。由于对SharePoint不是很熟练,导致每次写代码都得去Stack Overflow上去找代码。现将经常使用的相关代码总结如下,以留自己日后参考。     1.list item的创建: function createListItem(listTitle, data, callback) {

zhoulu001的专栏 3432

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

JavaScript对象模型-执行模型

[url=http://www.cnblogs.com/RicCC/archive/2008/02/15/javascript-object-model-execution-model.html]JavaScript对象模型-执行模型[/url]

Swifly的专栏 219

CSSOM.js完全指南:纯JavaScript实现的CSS解析器与对象模型详解

CSSOM.js是一个纯JavaScript实现的CSS对象模型(CSS Object Model)库,同时也是一个功能强大的CSS解析器。它允许开发者在JavaScript环境中操作CSS样式表、规则和样式声明,为前端开发提供了灵活的样式处理能力。本文将详细介绍CSSOM.js的核心功能、使用方法和实际应用场景,帮助开发者快速掌握这个实用的工具库。 ## 什么是CSSOM? CSSOM(CS

gitblog_00649的博客 696

Ruby和JavaScript对象模型的比较

概要 Ruby和JavaScript都是动态脚本语言,他们有许多地方是类似的。比如函数都是一等对象,都有高阶函数等等。。。但是我觉得最像的要属他们的对象模型,比如:他们的类型不伦不类,对象非要搞得像一个属性槽。 Ruby的对象模型 Ruby,一种为简单快捷面向对象编程而创的脚本语言。他的最大的特点就是面向对象的模型和元编程的能力,Ruby是完全面向对象的,没有任何的原始类型。要注意的是:Ru

ssjssh的专栏 1683

js对象模型

JavaScript对象模型是语言核心,主要包括对象创建、原型继承和属性操作。对象可通过字面量或构造函数创建,使用原型链实现继承。ES6类语法是构造函数的语法糖。属性描述符可控制属性行为,常用方法如Object.keys()获取属性键。注意浅拷贝与深拷贝的区别,Map对象比普通Object更灵活。性能优化建议避免频繁修改对象结构,大量相似对象使用构造函数,高频增删考虑Map。

2503_92740463的博客 292

JavaScript之BOM对象模型

BOM ECMAScript 是 JavaScript 的核心,但如果要在 Web 中使用 JavaScript,那么 BOM(浏览器对象模型)则无疑才是真正的核心。 BOM 提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关。多年来,缺少事实上的规范导致 BOM 有很多问题,因为浏览器提供商会按照各自的想法随意去扩展它。 W3C 为了把浏览器中JavaScript 最基本的部分标...

Cherish599的博客 258

JavaScript 对象模型-执行模型(一)

Javascript作为一个客户端的执行脚本语言,越来越受到行内的关注。开始在学习javascript时,根本没有对这种语言有深层次的理解,就开始使用了。起初只以为js的作用主要就是做本地化数据验证的,随着时间的增长,越发发现javascript的潜力很大。尤其在使用了Jquery和YUI之后。首先下面这篇文章介绍的是JS的基础。关于JS的学习资料有很多,如果只是用JS做做数据验证或者DOM控制,可能和这篇文章干系不大。但如果你对你new一个对象时,它内部操作是什么,或者,究竟Jquery和YUI这些JS的

pusongyang的专栏 652
上一篇: CSS(Cascading Style Sheet)
下一篇: JS - 高阶对象、高阶类或称Mixin模式
鹿夏
博客等级 码龄8年 24粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值