首页 > 编程语言 >JavaScript开发学习札记:一位Java后端程序员的成长之路

JavaScript开发学习札记:一位Java后端程序员的成长之路

时间:2024-08-29 21:55:36浏览次数:9  
标签:function Java name 对象 JavaScript 程序员 let console log

前言:

        这是一篇关于JavaScript的学习笔记,目的是针对java后端开发人员,快速入门并掌握JavaScript这门语言的基本使用,并且能够进入下一阶段框架的学习。

引言:

为什么学习 JavaScript?

JavaScript 是 web 开发人员必须学习的 3 门语言中的一门:

  1. HTML 定义了网页的内容(网页的结构)

  2. CSS 描述了网页的布局(网页的表现)

  3. JavaScript 控制了网页的行为(交互效果)

简单来说:我们使用HTML和CSS编写的网页都是静态的,现在我们想要让网页可以进行交互,变成动态的网页,就需要JavaScript来完成

JavaScript 简介

        JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。

扩展:了解即可

JavaScript 已经由 ECMA(欧洲电脑制造商协会)通过 ECMAScript 实现语言的标准化。

年份名称描述
1997ECMAScript 1第一个版本
1998ECMAScript 2版本变更
1999ECMAScript 3添加正则表达式 添加 try/catch
ECMAScript 4没有发布
2009ECMAScript 5添加 "strict mode",严格模式 添加 jsON 支持
2011ECMAScript 5.1版本变更
2015ECMAScript 6添加类和模块
2016ECMAScript 7增加指数运算符 (**) 增加 Array.prototype.includes

ECMAScript 6 也称为 ECMAScript 2015。

ECMAScript 7 也称为 ECMAScript 2016。

以上可以理解为各个版本的JavaScript,我们现在使用的JS指的就是ECMAScript6 -7的标准

JavaScript 是脚本语言

JavaScript 是一种轻量级的编程语言。

JavaScript 是可插入 HTML 页面的编程代码。

JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。

JS学习

js(JavaScript)的引入方式

  • 内部脚本:将js代码定义在HTML页面中

    • JavaScript代码必须位于<script> </script>标签之间

    • 在HTML文档中,可以在任意地方,放置任意数量的<script>

    • 一般会把脚本置于<body>元素的底部,可改善显示速度

    <script>
    alert("Hello JavaScript");
    </script>
  • 外部脚本:将js代码定义在外部js文件中,然后引入到HTML页面中

    • 外部js文件中,只包含js代码,不包含<script>标签

    • <script>标签不能自闭合(只能使用双标签)

    <script src="js/demo.js"></script>
    
    alert("Hello JavaScript");

注意:

<script> 标签可以放在网页的任意位置,但是由于加载顺序的原因,显示也会受到影响,但是后期如果要引入外部的js库的情况下,就需要放在body上方(需要外部js的支持,只能先加载)

小案例:修改页面内容

HTML:

<body>
    <p id="p1">Hello World!</p>
</body>
<script>
    let e =document.getElementById('p1')
    e.innerText="Hello JavaScript";
</script>

扩展:常见的输出语句

<script>
window.alert("Hello JavaScript");//浏览器弹出警告框
document.write("Hello JavaScript");//写入HTML,在浏览器展示
console.log("Hello JavaScript");//写入浏览器控制台
</script>

js基础语法

书写语法

  • 区分大小写:与Java一样,变量名、函数名以及其他一切都区分大小写的

  • 每行结尾的分号可有可无

  • 注释:

    • 单行注释://注释内容

    • 多行注释:/*注释内容*/

  • 大括号代表代码块

js不属于强类型语言,后面的分号可有可无,但是推荐加上,因为后面一些框架可能会对js进行优化(去掉所有空格),此时就需要分号作为语法分隔符

变量

  • JavaScript使用var关键字(variable的缩写)来声明变量。

  • JavaScript是一门弱类型语言,变量可以存放不同类型的值

  • 变量需要遵循如下规则:

    • 组成字符可以是任何字母、数字、下划线(_)或美元符号($)

    • 数字不能开头

    • 建议使用驼峰命名

  • ECMAScript6新增了let关键字来定义变量,用法类似var ,但声明的变量,只能在let关键字所在的代码块内有效、且不允许重复声明(可以重复赋值,但不能重复定义)

    • 可以理解为let为java中的局部变量

  • ECMAScript新增了const关键字,用来声明一个只读的常量,一旦声明,常量的值就不能改变

数据类型、运算符、流程控制语句

数据类型
  • JavaScript中分为:原始类型和引用类型

  • 原始类型(基本类型):

    • number:数字(整数、小数、NaN(Not a Number))

    • string:字符串、单双引皆可

    • boolean:布尔。true,false

    • null:对象为空

    • undefined:当声明的变量未初始化时,该变量的默认值是undefined

  • 使用typeof运算符可以获取数据类型:

    • <script>
      var a=20;
      alert(type0f(a));
      </script>
基本类型
undefined和null
  • 执行表达式或函数,没有返回结果,出现 undefined

  • 访问数组不存在的元素,访问对象不存在的属性,出现 undefined

  • 定义变量,没有初始化,出现 undefined

例:

console.log(1);     // 函数没有返回值, 结果是  undefined
let a = 10;         // 表达式没有返回值, 结果是 undefined
let b = [1,2,3];
console.log(b[10]); // 数组未定义元素是 undefined
let c = {"name":"张三"};
console.log(c.age); // 对象未定义属性是 undefined
let d;
console.log(d);     // 变量未初始化是 undefined

undefined和null的区别和联系

二者共同点

  • 都没有属性、方法 (基本类型都没有,有例外:string)

  • 二者合称 Nullish(只是一个称呼)

二者区别

  • undefined 由 js产生

  • null 由程序员提供


string

js 字符串三种写法

let a = "hello";  // 双引号
let b = 'world';  // 单引号
let c = `hello`;  // 反引号

js的字符串拼接

需求:拼接 URI 的请求参数,如

传统方法拼接:

let name = ; // zhang li ...
let age = ; // 18 20 ...

let url = "/test?name=" + name + "&age=" + age;

模板字符串方式:(模版字符串只能使用反引号)

let name = ; // zhang li ...
let age = ; // 18 20 ...

let url = `/test?name=${name}&age=${age}`;

使用模版字符串是为了提高可读性


number和bigint

number 类型标识的是双精度浮动小数,例如

10 / 3;   // 结果 3.3333333333333335

既然是浮点小数,那么可以除零

10 / 0;	  // 结果 Infinity 正无穷大
-10 / 0;  // 结果 -Infinity 负无穷大

浮点小数都有运算精度问题,例如

2.0 - 1.1; // 结果 0.8999999999999999

bigint

可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n

alert(10n/3n)  //结果为3
boolean
  • Truthy

  • Falsy

在 js 中,并不是 boolean 才能用于条件判断,你可以在 if 语句中使用【数字】、【字符串】... 作为判断条件

let b = 1;

if(b) { // true
    console.log("进入了");
}

这时就有一个规则,当需要条件判断时,这个值被当作 true 还是 false,当作 true 的值归类为 truthy,当作 false 的值归类为 falsy

下面值都是 falsy

  • false

  • Nullish (null, undefined)

  • 0, 0n, NaN

  • "" '' ``即长度为零的字符串

剩余的值绝大部分都是 truthy

有几个容易被当作 falsy 实际是 truthy 的

  • "false", "0" 即字符串的 false 和 字符串的零(本质上还是有值的字符串,为true)

  • [] 空数组

  • {} 空对象

symbol

很少使用

symbol是一个ES6标准种新增的一种基本数据类型,在JavaScript中,共有七种基本数据类型:string、number、bigint、boolean、null、undefined、symbol。并且除了null和undefined之外,每个基本类型都有其包装对象。

symbol 的值是通过 Symbol() 函数生成,每一个 symbol 的值都是唯一的,并且 symbol 类型的值可以作为对象的属性标识符使用,这也是 symbol 类型设计的目的。


类型转换
  • 字符串类型转为数字

    • 将字符串字面值转为数字,如果字面值不是数字,则转为NaN

  • 其他类型转为boolean

    • number:0和NaN为false,其他均转为true

    • string:空字符串为false,其他均转为true

    • null和undefined:均转为false

字符串转数字

parseInt("10"); 	// 结果是数字 10 
parseInt("10.5");	// 结果是数字 10, 去除了小数部分
parseInt("10") / 3; // 结果仍视为 number 浮点数, 因此结果为 3.3333333333333335

parseInt("abc");	// 转换失败,结果是特殊值 NaN (Not a Number)

也可以使用字符串减去零的方式完成字符串的转换成数字,因为在减法运算时,字符串已经转换成数字类型了


引用类型(对象类型):
1.Function
定义函数

方式一:

function 函数名(参数) {
    // 函数体
    return 结果;
}

function add(a, b) {
    return a + b;
}

方式二:

var 函数名 = function(参数) {
    // 函数体
    return 结果;
}

var add = function(a, b) {
    return a + b;
}

函数:是被设计用来执行特定任务的代码块

因为js的是弱类型的语言,所以使用函数时要注意:

  • 形式参数不需要类型

  • 返回值也不需要定义类型,可以在函数内部直接使用return返回即可(如果没有返回值,不写return语句即可)

调用函数

add(1, 2);     // 返回 3

js 中的函数调用特点:对参数的类型个数都没有限制,例如

add('a', 'b');  // 返回 ab
add(4, 5, 6);   // 返回 9, 第三个参数没有被用到, 不会报错
add(1);			// 返回 NaN, 这时 b 没有定义是 undefined, undefined 做数学运算结果就是 NaN

js调用函数时,可以传递任意个数参数,只不过,超出定义部分的参数不会被接收

默认参数

js(如果调用方法时,没有传入参数,则使用默认参数)

function pagination(page = 1, size = 10) {
    console.log(page, size);
}
匿名函数

语法(建议将匿名函数用小括号包括起来,表示该函数是一个表达式)

(function (参数) {
    // 函数体
    return 结果;
})

(function(a,b){
    return a + b;
})

第一种场景:定义完毕后立刻调用,只调用一次

(function(a,b){
    return a + b;
})(1,2)

第二种场景:作为其它对象的方法,例如

页面有元素

<p id="p1">点我啊</p>

此元素有一个 onclick 方法,会在鼠标单击这个元素后被执行,onclick 方法刚开始的值是 null,需要赋值后才能使用(函数可以被用来赋值,因为在js中函数也被认定为一个对象)

document.getElementById("p1").onclick = (function(){
    console.log("鼠标单击了...");
});
箭头函数

(可以理解为匿名函数的简化写法)

(参数) => {
    // 函数体
    return 结果;
}
  • 如果没有参数,() 还是要保留

  • 如果只有一个参数,() 可以省略

  • 如果函数体内只有一行代码,{} 可以省略

  • 如果这一行代码就是结果,return 可以省略

document.getElementById("p1").onclick = () =>  console.log("aa");
函数是对象
//在Javascript中,函数本身也是对象

以下形式在 js 中非常常见!

  • 可以参与赋值,具名函数(有具体名字的函数)也能参与赋值
function abc() {
    console.log("bb");
}

document.getElementById("p1").onclick = abc; //函数本身作为值进行传递,不是调用函数获取返回值
  • 函数也是对象,对象有属性、有方法,执行 console.dir(abc),输出结果如下
  • ƒ abc()
        arguments: null
        caller: null
        length: 0
        name: "abc"
        ➡prototype: {constructor: ƒ}
        [[FunctionLocation]]: VM1962:1
        ➡[[Prototype]]: ƒ ()
        ➡[[Scopes]]: Scopes[1]
    • 其中带有 f 标记的是方法,不带的是属性

    • 带有 ➡ 符号的可以继续展开,限于篇幅省略了

    • 带有 [[ ]] 的是内置属性,不能访问,只能查看

    • 相对重要的是 [[Prototype]][[Scopes]] 会在后面继承和作用域时讲到

  • 可以作为方法参数 (这里的b成为高阶函数)
function a() {
    console.log('a')
}

function b(fn) {          // fn 将来可以是一个函数对象
    console.log('b')
    fn();                 // 调用函数对象
}

b(a)
  • 可以作为方法返回值(这里的c也可以叫做高阶函数)
function c() {
    console.log("c");
    function d() {
        console.log("d");
    }
    return d;
}

c()()  //返回值是一个函数, 再次进行函数调用 (两次函数调用)

函数作用域

函数可以嵌套(js 代码中很常见,只是嵌套的形式更多是匿名函数,箭头函数)

function a() {
    function b() {        
    }
}

看下面的例子

function c() {
    var z = 30;
}

var x = 10;
function a() {
    var y = 20;
    function b() {
        // 看这里
        console.log(x, y);
    }
    b();
}
a();

对于嵌套的函数b,他的作用域从自身外部函数,到全局作用域一共三层

  • 以函数大括号为分界线划定作用域,所有函数之外是全局作用域

  • 查找变量时,由内向外查找

    • 在内层作用域找到变量,就会停止查找,不会再找外层

    • 所有作用域都找不到变量,报错

  • 作用域本质上是函数对象的属性,可以通过 console.dir 来查看调试(就是scopes属性)

闭包
var x = 10;
function a() {
    var y = 20;
    function b() {
        console.log(x,y);
    }
    return b;
}
a()();  // 在外面执行了 b
  • 函数定义时,它的作用域已经确定好了,因此无论函数将来去了哪,都能从它的作用域中找到当时那些变量(因为作用域本质上是函数的一个属性)

  • 别被概念忽悠了,闭包就是指函数能够访问自己的作用域中变量

let、var 与作用域

如果函数外层引用的是 let 变量,那么外层普通的 {} 也会视为作用域边界,最外层的 let 也占一个 script 作用域

let x = 10; 
if(true) {
    let y = 20;
    function b() {
        console.log(x,y);
    }
    console.dir(b);
}

如果函数外层引用的是 var 变量,外层普通的 {} 不会视为边界

var x = 10; 
if(true) {
    var y = 20;
    function b() {
        console.log(x,y);
    }
    console.dir(b);
}

如果 var 变量出现了重名,则他俩会被视为同一作用域中的同一个变量

var e = 10; 
if(true) {
    var e = 20;
    console.log(e);	// 打印 20
}
console.log(e);		// 因为是同一个变量,还是打印 20

如果是 let,则视为两个作用域中的两个变量

let e = 10; 
if(true) {
    let e = 20;	
    console.log(e);	// 打印 20
}
console.log(e);		// 打印 10

要想里面的 e 和外面的 e 能区分开来,最简单的办法是改成 let,或者用函数来界定作用域范围(只要保证变量不在同一个作用域,则不是同一个变量)

var e = 10; 
if(true) {
    function b() {
        var e = 20;
    	console.log(e);
    }
    b();
}
console.log(e);

简而言之:可以理解为let定义的变量为局部的,var定义的变量为全局的

2.JS对象

主要学习三大类对象:基础对象,浏览器对象,文档对象

基础对象是js中自带的一些对象

BOM对象(将浏览器中的组件封装成对象)

DOM对象(将html中的标签封装成对象)

Array
  • JavaScriprt中Array对象用于定义数组

  • 定义

    • var 变量名 =new Array(元素列表); //方式一
      var arr =new Array(1,2,3,4);
    • var 变量名 =[元素列表];//方式二  
      var arr=[1,2,3,4];
  • 访问

    • arr[索引]=值;
      arr[10]="hello";
  • js中的数组类似java中的集合,长度可变,类型可变。

例:

// 创建数组
let arr = [1,2,3]; 

// 获取数组元素
console.log(arr[0]); // 输出 1

// 修改数组元素
array[0] = 5;		 // 数组元素变成了 [5,2,3]

// 遍历数组元素,其中 length 是数组属性,代表数组长度
for(let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

常用API

  • push、shift、splice

let arr = [1,2,3]; 

arr.push(4);    	// 向数组尾部(右侧)添加元素, 结果 [1,2,3,4]
arr.shift();		// 从数组头部(左侧)移除元素, 结果 [2,3,4]
arr.splice(1,1);	// 删除【参数1】索引位置的【参数2】个元素,结果 [2,4]
  • join(字符串连接)

let arr = ['a','b','c'];

arr.join(); 		// 默认使用【,】作为连接符,结果 'a,b,c'
arr.join('');		// 结果 'abc'
arr.join('-');		// 结果 'a-b-c'
  • map、filter、forEach

let arr = [1,2,3,6];

function a(i) {   // 代表的新旧元素之间的变换规则
    return i * 10
}

// arr.map(a) // 具名函数,结果 [10,20,30,60]

// arr.map( (i) => {return i * 10} ); // 箭头函数
arr.map( i => i * 10 ); // 箭头函数
  • 传给 map 的函数,参数代表旧元素,返回值代表新元素

map 的内部实现(伪代码)

function map(a) { // 参数是一个函数
    let narr = [];
    for(let i = 0; i < arr.length; i++) {
        let o = arr[i]; // 旧元素
        let n = a(o);   // 新元素
        narr.push(n);
    }
    return narr;
}

filter 例子

let arr = [1,2,3,6];
arr.filter( (i)=> i % 2 == 1 ); // 结果 [1,3]
  • 传给 filter 的函数,参数代表旧元素,返回 true 表示要留下的元素

forEach 例子

let arr = [1,2,3,6];

/*for(let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}*/

arr.forEach( (i) => console.log(i) );

两个称呼

  • 高阶函数,map,filter,forEach

  • 回调函数,例如作为参数传入的函数

String
  • 字符串:既像基本类型string,又像对象object

  • 定义

    • var 变量名 =new String("..."); //方式一
      var str =new String("Hello String");
    • var 变量名 ="...";//方式二  
      var str="Hello String";
  • 属性:length 描述:字符串的长度

  • 方法

    • charAt() 描述:返回指定位置的字符

    • indexOf() 描述:检索字符串

    • trim() 描述:去除字符串两边的空格

    • substring() 描述:提取字符串中两个指定的索引号之间的字符

Object

JavaScript自定义对象

  • 定义格式

    • var 对象名={
      			属性名1:属性值1,
      			属性名2:属性值2,
      			属性名3:属性值3,
      			函数名称:function(){}
      		};
      		
      		var user={
      			name="Tom",
      			age:20,
      			gender:"male",
      			eat:function(){
      				alert("吃饭...");
      			}
      		};
      		//函数的省略形式
      		var user={
      			name="Tom",
      			age:20,
      			gender:"male",
      			eat(){
      				alert("吃饭...");
      			}
      		};
  • 调用格式

    • //调用格式
      对象名.属性名;
      对象名.函数名();

Object语法

        get和set方法

let obj = {
    属性名: 值,
    方法名: 函数,
    get 属性名() {},
    set 属性名(新值) {}
}

创建一个对象的多种方式如下:

例1

let stu1 = {
    name: "小明",
    age: 18,
    study: function(){
        console.log(this.name + "爱学习");
    }    
}

例2

let name = "小黑";
let age = 20;
let study = function(){
    console.log(this.name + "爱学习");
}

let stu2 = { name, age, study }  //解构运算符进行对象创建,运算符中会讲到,现在可以理解为将变量直接作为对象的属性进行创建对象

例3(重点)

let stu3 = {
    name: "小白",
    age: 18,
    study(){
        console.log(this.name + "爱学习");//对象方法这么写,仅限于对象内部
    }    
}

例4:(书写对象中的get和set方法)

let stu4 = {
    _name: null, /*类似于java中私有成员变量*/
    get name() {
        console.log("进入了get");
        return this._name;
    },
    set name(name) {
        console.log("进入了set");
        this._name = name;
    }
}

        调用 get,set(不是直接调用方法,而是对象名.属性名赋值时默认调用set,对象名.属性名=值取值时默认调用get)

stu4.name = "小白"

console.log(stu4.name)

        js中并没有私有属性的概念,加上下划线只是一种约定俗成的规则,我们还是可以直接访问该属性的,但是一般不这样做

特色:属性增删

对比一下 Java 中的 Object

  • Java 的 Object 是以类作为模板来创建,对象不能脱离类模板的范围,一个对象的属性、能用的方法都是在编译时确定好的

  • js 的对象,不需要什么模板,它的属性和方法可以随时增加或删减

let stu = {name:'张三'};
stu.age = 18;					// 添加属性
delete stu.age;					// 删除属性

stu.study = function() {		// 添加方法
    console.log(this.name + "在学习");
}

添加 get,set,需要借助 Object.definePropery方法

let stu = {_name:null};

Object.defineProperty(stu, "name", {
    get(){
        return this._name;
    },
    set(name){
        this._name = name;
    }
});
  • 参数1:目标对象

  • 参数2:属性名

  • 参数3:get,set 的定义

特色:this

先来对 Java 中的 this 有个理解

public class TestMethod {

    static class Student {
        private String name;

        public Student(String name) {
            this.name = name;
        }

        public void study(Student this, String subject) {
            System.out.println(this.name + "在学习 " + subject);
        }
    }

    public static void main(String[] args) {
        Student stu = new Student("小明");
        
        // 下面的代码,本质上是执行 study(stu, "java"),因此 this 就是 stu
        stu.study("java"); 
    }
}
  • Java 中的 this 是个隐式参数

  • Java 中,我们说 this 代表的就是调用方法的那个对象

js 中的 this 也是隐式参数,但它与函数运行时上下文相关

例如:

1.一个“落单”的函数

function study(subject) {
    console.log(this.name + "在学习 " + subject)
}

测试一下

study("js");  // 输出 在学习 js

        没有获取到输入的值,这是因为在函数执行时,全局对象 window 被当作了 this,window 对象的 name 属性是空串,所以不显示

2.同样的函数,如果作为对象的方法

let stu = {
    name:"小白",
    study
}

        这种情况下,会将当前对象作为 this

stu.study('js'); 	// 输出 小白在学习 js
还可以动态改变 this

let stu = {name:"小黑"};
study.call(stu, "js");	// 输出 小黑在学习 js

        这回 study 执行时,就把 call 的第一个参数 stu 作为 this

3.一个例外是,在箭头函数内出现的 this,以外层 this 理解

用匿名函数

let stu = {
    name: "小花",
    friends: ["小白","小黑","小明"],
    play() {
        this.friends.forEach(function(e){
            console.log(this.name + "与" + e + "在玩耍");
        });
    }
}
stu.play()
  • this.name 所在的函数是“落单”的函数,因此 this 代表 window对象

输出结果为

与小白在玩耍
与小黑在玩耍
与小明在玩耍

用箭头函数

let stu = {
    name: "小花",
    friends: ["小白","小黑","小明"],
    play() {
        this.friends.forEach(e => {
            console.log(this.name + "与" + e + "在玩耍");
        })
    }    
}
  • this.name 所在的函数是箭头函数,因此 this 要看它外层的 play 函数,play 又是属于 stu 的方法,因此 this 代表 stu 对象

输出结果为

小花与小白在玩耍
小花与小黑在玩耍
小花与小明在玩耍

不用箭头函数的做法

let stu = {
    name: "小花",
    friends: ["小白","小黑","小明"],
    play() {
        let me = this;
        this.friends.forEach(function(e){
            console.log(me.name + "与" + e + "在玩耍");
        });
    }
}
特色:原型继承

(js中指的是继承发生在两个对象之间,而不是两个类之间)

let father = {
    f1: '父属性',
    m1: function() {
        console.log("父方法");
    }
}

let son = Object.create(father); //调用方法,以father对象为原型创建son对象

console.log(son.f1);  // 打印 父属性
son.m1();			  // 打印 父方法
  • father 是父对象,son 去调用 .m1 或 .f1 时,自身对象没有,就到父对象找

  • son 自己可以添加自己的属性和方法

  • son 里有特殊属性 __proto__ 代表它的父对象,js 术语: son 的原型对象

  • 不同浏览器对打印 son 的 __proto__ 属性时显示不同

    • Edge 打印 console.dir(son) 显示 [[Prototype]]

    • Firefox 打印 console.dir(son) 显示 <prototype>

特色:基于函数的原型继承

出于方便的原因,js 又提供了一种基于函数的原型继承

函数职责

  1. 负责创建子对象,给子对象提供属性、方法,功能上相当于构造方法

  2. 函数有个特殊的属性 prototype,它就是函数创建的子对象的父对象 注意!名字有差异,这个属性的作用就是为新对象提供原型

function cons(f2) {
    // 创建子对象(this), 给子对象提供属性和方法
    this.f2 = f2;
    this.m2 = function () {
        console.log("子方法");
    }
}
// cons.prototype 就是父对象
cons.prototype.f1 = "父属性";
cons.prototype.m1 = function() {
    console.log("父方法");
}

配合 new 关键字,创建子对象

let son = new cons("子属性")

子对象的 __proto__ 就是函数的 prototype 属性

JSON
  • 概念:JavaScript Object Notation ,JavaScript对象标记法

  • JSON是通过JavaScript对象标记法书写的文本

  • 由于其语法简单,层次结构鲜明,多用于作为数据载体,在网络中进行数据传输

可以理解为,JSON本质上就是一个字符串,作用是为了作为数据的载体在网络上进行传输

json常用于作为数据的载体,因为xml格式作为数据传输载体过于臃肿,可以用json代替,json与自定义js对象格式相似,用来承载复杂数据,不过json中所有的键必须用双引号标注。

JSON基础语法

var 变量名='{"key1":value1,"key2":value2,...}';
var userStr='{"name":"Jerry","age":18,"addr":["北京","上海","河南"]}';

value的数据类型为:

  • 数字(整数或浮点数)

  • 字符串(在双引号中)

  • 逻辑值(true或false)

  • 数组(在方括号中)

  • 对象(在花括号中)

  • null

使用

  • 前端向后端传递复杂数据时,可以使用json

  • 将js对象转换成json格式数据,function函数不会保留

  • json本身只是一个字符串不能直接使用对象调用属性和方法的形式,必须先转化

JSON字符串转为JS对象

var jsObject=JSON.parse(userStr);

JS对象转为JSON字符串

var jsonStr =JSON.stringify(jsObject);

了解更多:

js对象和JSON字符串的区别详解:

一个 json 对象可以长这样:

{
 "name":"VaporGas",
 "age":22
}

一个 js 对象可以长这样:

{
 name:"VaporGas",
 age:22
}

那么他们的区别在哪儿呢?我总结了这么几点

  1. 本质不同

    • json 对象本质上是个字符串,它的职责是作为客户端和服务器之间传递数据的一种格式,它的属性只是样子货

    • js 对象是切切实实的对象,可以有属性方法

  1. 语法细节不同

    • json 中只能有 null、true|false、数字、字符串(只有双引号)、对象、数

    • json 中不能有除以上的其它 js 对象的特性,如方法等

    • json 中的属性必须用双引号引起来

json 字符串与 js 对象的转换

JSON.parse(json字符串);  // 返回js对象
JSON.stringify(js对象);  // 返回json字符串
动态类型

java是强类型的语言(变量和值都有类型),js是弱类型的语言(值有类型,变量没有类型)

静态类型语言,如 Java,值有类型,变量也有类型、赋值给变量时,类型要相符

int a = 10;
String b = "abc";

int c = "abc";  // 错误

而 js 属于动态类型语言,值有类型,但变量没有类型,赋值给变量时,没要求

例如

let a = 200;

let b = 100;
b = 'abc';
b = true;

动态类型看起来比较灵活,但变量没有类型,会给后期维护带来困难,例如

function test(obj) {
    // obj 的类型未知,必须根据不同类型做出相应的容错处理
}

运算符

算术运算符:+-*/%++--

赋值运算符:=+=-=*=/=%=

比较运算符:>< ,<=, >= ,!=,==, ===

逻辑运算符:&&||, !

三元运算符:条件表达式?true_value:false_value

=====的区别

  • ==会进行类型转换 ,===不会进行类型转换

var a = 10;
alert(a =="10");//true
alert(a ==="10");//false
alert(a === 10); //true

比较重要的一些运算符:

===

严格相等运算符,用作逻辑判等

1 == 1    	// 返回 true 
1 == '1'	// 返回 true,会先将右侧的字符串转为数字,再做比较
1 === '1'	// 返回 false,类型不等,直接返回 false

typeof 查看某个值的类型

typeof 1	// 返回 'number'
typeof '1'	// 返回 'string'
||

需求,如果参数 n 没有传递,给它一个【男】

推荐做法

function test(n = '男') {//是一种赋默认值的方式,如果有值,会替代默认值
    console.log(n);
}

你可能的做法

function test(n) {
    if(n === undefined) {
        n = '男';
    }
    console.log(n);
}

还可能是这样

function test(n) {
    n = (n === undefined) ? '男' : n;  //三元运算符
    console.log(n);
}

以上都是一些老旧代码中可能的做法(不推荐)

使用||运算符:

function test(n) {
    n = n || '男';
    console.log(n);
}

它的语法是

值1 || 值2

如果值1 是 Truthy,返回值1,如果值1 是 Falsy 返回值 2

???
??

需求,如果参数 n 没有传递或是 null,给它一个【男】

如果用传统办法

function test(n) {
    if(n === undefined || n === null) {
        n = '男';
    }
    console.log(n);
}

用 ??

function test(n) {
    n = n ?? '男';
    console.log(n);
}

语法

值1 ?? 值2
  • 值1 是 nullish,返回值2

  • 值1 不是 nullish,返回值1

?.

需求,函数参数是一个对象,可能包含有子属性

例如,参数可能是

let stu1 = {
    name:"张三",
    address: {
        city: '北京'
    }
};

let stu2 = {
    name:"李四"
}

let stu3 = {
    name:"李四",
    address: null
}

现在要访问子属性(出现异常,因为address对象不存在city属性)

function test(stu) {
    console.log(stu.address.city)
}

现在希望当某个属性是 nullish 时,短路并返回 undefined,可以用?.

function test(stu) {
    console.log(stu.address?.city)
}

用传统办法

function test(stu) {
    if(stu.address === undefined || stu.address === null) {
        console.log(undefined);
        return;
    }
    console.log(stu.address.city)
}

...

展开运算符

作用1:打散数组,把元素传递给多个参数

let arr = [1,2,3];

function test(a,b,c) {
    console.log(a,b,c);
}

需求,把数组元素依次传递给函数参数

传统写法

test(arr[0],arr[1],arr[2]);		// 输出 1,2,3

展开运算符写法

test(...arr);					// 输出 1,2,3
  • 打散可以理解为【去掉了】数组外侧的中括号,只剩下数组元素

作用2:复制数组或对象

数组

let arr1 = [1,2,3];
let arr2 = [...arr1];		// 复制数组

对象

let obj1 = {name:'张三', age: 18};

let obj2 = {...obj1};		// 复制对象

注意:展开运算符复制属于浅拷贝,例如(如果只有一层,则被拷贝过去的改变不会影响被拷贝对象,如果有多层,拷贝的二层及以下就是深拷贝,改动会造原拷贝改变)

let o1 = {name:'张三', address: {city: '北京'} }

let o2 = {...o1};

作用3:合并数组或对象

合并数组

let a1 = [1,2];
let a2 = [3,4];

let b1 = [...a1,...a2];		// 结果 [1,2,3,4]
let b2 = [...a2,5,...a1]	// 结果 [3,4,5,1,2]

合并对象

let o1 = {name:'张三'};
let o2 = {age:18};
let o3 = {name:'李四'};

let n1 = {...o1, ...o2};	// 结果 {name:'张三',age:18}

let n2 = {...o3, ...o2, ...o1}; // 结果{name:'李四',age:18}
  • 复制对象时出现同名属性,后面的会覆盖前面的

[] {}

解构运算符

[]

用在声明变量时

let arr = [1,2,3];

let [a, b, c] = arr;	// 结果 a=1, b=2, c=3

用在声明参数时

let arr = [1,2,3];

function test([a,b,c]) {
    console.log(a,b,c) 	// 结果 a=1, b=2, c=3
}

test(arr);

{}

用在声明变量时

let obj = {name:"张三", age:18};

let {name,age} = obj;	// 结果 name=张三, age=18

用在声明参数时 (注意需要变量名称与对象的属性名一致)

let obj = {name:"张三", age:18};

function test({name, age}) {
    console.log(name, age); // 结果 name=张三, age=18
}

test(obj)

控制语句
  • if ... else

  • switch

  • while

  • do ... while

  • for

  • for ... in

  • for ... of

  • try ... catch

本文只介绍较难理解的的后三个控制语句

for in

主要用来遍历对象

let father = {name:'张三', age:18, study:function(){}};

for(const n in father) {
    console.log(n);
}
  • 其中 const n 代表遍历出来的属性名(为什么使用const,是因为for in 有严格的迭代过程,每次遍历都会取出一个新的const,每个const都是不可变的)

  • 注意1:方法名也能被遍历出来(它其实也算一种特殊属性)

  • 注意2:遍历子对象时,父对象的属性会跟着遍历出来

let son = Object.create(father);
son.sex = "男";

for(const n in son) {
    console.log(n);
}
  • 注意3:在 for in 内获取属性值,要使用 [] 语法,而不能用 . 语法

for(const n in son) {
    console.log(n, son[n]);//n是属性名,son[n]是对应的属性值
}
for of

主要用来遍历数组,也可以是其它可迭代对象,如 Map,Set 等

let a1 = [1,2,3];

for(const i of a1) {
    console.log(i);
}

let a2 = [
    {name:'张三', age:18},
    {name:'李四', age:20},
    {name:'王五', age:22}
];

for(const obj of a2) {
    console.log(obj.name, obj.age);
}

for(const {name,age} of a2) {
    console.log(name, age);
}
try catch
let stu1 = {name:'张三', age:18, address: {city:'北京'}};
let stu2 = {name:'张三', age:18};

function test(stu) {
    try {
        console.log(stu.address.city)   
    } catch(e) {
        console.log('出现了异常', e.message)
    } finally {
        console.log('finally');
    }
}
BOM
  • 概念:Browser Object Model 浏览器对象模型,允许JavaScript与浏览器直接对话,JavaScript将浏览器的各个组成部分封装为对象。

  • 组成:

    • Window:浏览器窗口对象

    • Navigator:浏览器对象

    • Screen:屏幕对象

    • History:历史记录对象

    • Location:地址栏对象

Window
  • 介绍:浏览器窗口对象。

  • 获取:直接使用window,其中 window.可以省略。

    • window.alert("Hello window");

    • alert("Hello window");

  • 属性

    • history:对 History 对象的只读引用。

    • location:用于窗口或框架的 Location 对象。

    • navigator:对 Navigator 对象的只读引用。

  • 方法

    • alert():显示带有一段消息和一个确认按钮的警告框。

    • confirm():显示带有一段消息以及确认按钮和取消按钮的对话框。

    • setlnterval():按照指定的周期(以毫秒计)来调用函数或计算表达式。

    • setTimeout():在指定的毫秒数后调用函数或计算表达式。

Location
  • 介绍:地址栏对象

  • 获取:使用window.location获取,其中window.可以省略

  • 属性

    • href:设置或返回完整的URL

    • location.href="https://www.baidu.com"

以上代码先显示当前地址栏的地址信息,然后,跳转到指定的网址。


DOM

HTML文档被浏览器加载并解析后,会封装成对应的对象,同时在浏览器的内存中形成DOM树

  • 概念:Document Object Model,文档对象模型

  • 将标记语言的各个组成部分封装为对应的对象:

    • Document:整个文档对象

    • Element:元素对象

    • Attribute:属性对象

    • Text:文本对象

    • Comment:注释对象

js通过DOM和事件监听,控制网页的行为。

  • JavaScript通过DOM,就能够对HTML进行操作:

    • 改变HTML元素的内容

    • 改变HTML元素的样式(CSS)

    • 对HTML DOM事件作出反应

    • 添加和删除HTML元素

W3C DOM由以下三部分组成:

  • 核心DOM - 针对任何结构化文档的标准模型。

    • Document:整个文档对象

    • Element:元素对象

    • Attribute:属性对象

    • Text:文本对象

    • Comment:注释对象

  • XML DOM - 针对XML文档的标准模型。

  • HTML DOM - 针对HTML文档的标准模型。

DOM获取元素对象

获取对应的元素对象之后,就能对元素对象进行相关的操作了

事件监听

事件:就是发生在HTML元素上的动作

事件监听:就是当动作发生时,执行相应的操作

事件绑定:

        注意:在属性上绑定事件,是方法的调用,因此需要加()表示调用此方法,如果需要传入参数则写入准确的参数。此方法可以传参数;

        而通过dom元素属性进行绑定一般不传递参数,不写()是因为把函数作为对象(参数)传入

常见的事件

总结,以上是我学习js的一点笔记总结,推荐去一些教学网站(例如菜鸟教程)进一步学习

较为深刻的理解一下:JavaScript是一个基于客户端浏览器,基于对象和事件驱动式的网页脚本语言

标签:function,Java,name,对象,JavaScript,程序员,let,console,log
From: https://blog.csdn.net/weixin_52937170/article/details/141688070

相关文章

  • java.time包时间类浅谈
    Java早期日期时间API:java.util.Date与java.util.Calendar一、背景在Java的早期版本中,处理日期和时间的需求主要由java.util.Date类和随后加入的java.util.Calendar类来满足。这两个类在Java1.0和Java1.1中分别被引入,为Java程序提供了基本的日期和时间操作能力。然而,随着......
  • 一篇文章讲清楚Java中的反射
    介绍每个类都有一个Class对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的.class文件,该文件内容保存着Class对象。类加载相当于Class对象的加载。类在第一次使用时才动态加载到JVM中,可以使用Class.forName("com.mysql.jdbc.Driver")这种方式来控制类的......
  • 2024年高频Java面试题
    1、java反射的作用与原理1、定义:反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能够调用它的任意一个方法。在java中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。这种动态获取的信息以及动态调用对象的方法的功能称为Ja......
  • 第四章 Java核心类库 第二节 常用Java类库
    1.Math类与常用数学方法首先,我们来看一下Math类。Math类简介:Math类提供了一组用于数学运算的静态方法,包括求绝对值、取整、平方根、幂运算等常见操作。这些方法都是静态的,意味着我们可以直接通过类名调用它们。常用方法:abs():返回绝对值。ceil()和floor():分别返回向......
  • 全栈程序员 | 精通安卓、鸿蒙,小程序,Java、Vue.js、SpringBoot及更多技术
    我是一个全栈程序员,擅长多种开发技术,包括安卓开发、Java编程、Vue.js、SpringBoot以及小程序开发等。我在技术上有广泛的涉猎,并致力于将创新解决方案应用于实际项目中。无论是开发高性能的安卓应用,还是构建响应式网页、实现复杂的后端功能,我都能提供专业的技术支持和高质量的代......
  • java中的enum-java中特殊的class;通过字节码来分析enum构成
    §1 先思考一个问题先思考一个问题:我们在enum类里,可以直接使用 values() 或 valueOf(Stringname) 方法,我们也没有在enum类里定义这两个方法,怎么就能直接使用呢? 这里先按下不表。下面是正文。§2enum类及其编译后的字节码在java编程中,我们经常会定义和使用枚举。简......
  • 计算机毕业设计选题推荐-在线音乐网站-音乐专辑商城-Java/Python项目实战
    ✨作者主页:IT研究室✨个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。☑文末获取源码☑精彩专栏推荐⬇⬇⬇Java项目Python项目安卓项目微信小程序项目......
  • 计算机毕业设计选题推荐-中药材进存销管理系统-Java/Python项目实战
    ✨作者主页:IT研究室✨个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。☑文末获取源码☑精彩专栏推荐⬇⬇⬇Java项目Python项目安卓项目微信小程序项目......
  • Java——Stream 流的使用详解
    Stream 是一个可以用于操作集合、数组等数据源的API,主要进行数据的转换、筛选、聚合等操作这样做可以避免显式地使用迭代器或者循环来操作集合,提高代码的可读性和简洁性特点: 1、无存储性:是基于数据源的对象,本身不存储元素,而是通过管道将数据源元素传递给操作2......
  • Java中super关键字的学习
    super关键字目录super关键字1.访问父类的成员变量2.调用父类的方法3.调用父类的构造方法4.在实现接口的类中调用接口的默认方法注意事项在Java中,super是一个关键字,它主要用于在子类中引用父类的成员(包括字段、方法和构造方法),或者用于解决子类和父类之间的命名冲突。以下是s......