3 JavaScript 对象与内置对象

声明:本人前端学习笔记的所有内容均为b站上pink老师课程的学习笔记,如果想详细了解的可以搜索以下网址:

  1. H5C3+移动布局: 黑马程序员pink老师前端入门视频教程 HTML5+CSS3+移动端布局-flex布局rem布局响应式布局摹客蓝湖使用-简单有趣好玩
  2. JavaScript系列 :JavaScript基础语法-dom/bom-es6-jQuery-数据可视化echarts-包含笔记源码作业黑马程序员pink老师前端入门视频教程(持续更新)

文章目录

  • 一、JavaScript 对象
    • 1. 对象
    • 2. 创建对象的三种方式
      • 2.1 利用字面量创建对象
      • 2.2 利用new Object创建对象
      • 2.3 利用构造函数创建对象
    • 3. new 关键字
    • 4. 遍历对象属性
  • 二、JavaScript 内置对象
    • 1. 内置对象
    • 2. 查文档
    • 3. Math 对象
    • 4. 日期对象
    • 5. 数组对象
      • 5.1 检测是否为数组
      • 5.2 添加删除数组元素的方法
      • 5.3 数组排序
      • 5.4 数组索引方法
      • 5.5 数组转换为字符串
      • 5.6 数组的其他方法
    • 6. 字符串对象
      • 6.1 基本包装类型
      • 6.2 字符串的不可变
      • 6.3 根据字符返回位置
      • 6.4 根据位置返回字符(重点)
      • 6.5 字符串操作方法(重点)
      • 6.6 replace()方法
      • 6.7 split()方法
  • 三、JavaScript 简单类型与复杂类型
    • 1. 简单类型与复杂类型
    • 2. 堆和栈
    • 3. 简单类型与复杂类型传参


一、JavaScript 对象

1. 对象

现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如,一本书、一辆汽车、一个人可以是“对象”,一个数据库、一张网页、一个与远程服务器的连接也可以是“对象”。

在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。

对象是由属性和方法组成的。

  • 属性:事物的特征,在对象中用属性来表示(常用名词)
  • 方法:事物的行为,在对象中用方法来表示(常用动词)

为什么需要对象?

保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。如果要保存一个人的完整信息呢?

例如,将“张三疯”的个人的信息保存在数组中的方式为:

var arr = [‘张三疯’, ‘男', 128,154];

JS 中的对象表达结构更清晰,更强大。张三疯的个人信息在对象中的表达结构如下:

person.name = ‘张三疯';
person.sex = ‘男';
person.age = 128;
person.height = 154

2. 创建对象的三种方式

在 JavaScript 中,现阶段我们可以采用三种方式创建对象(object):

  • 利用字面量创建对象
  • 利用new Object 创建对象
  • 利用构造函数创建对象

2.1 利用字面量创建对象

对象字面量:就是花括号{ } 里面包含了表达这个具体事物(对象)的属性和方法。{ } 里面采取键值对的形式表示

  • 键:相当于属性名
  • 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)
var star = {
     
    name : 'pink', //注意这里是逗号
    age : 18,
    sex : '男', 
    sayHi : function(){
     
    	alert('大家好啊~');
    }
};

对象的调用

  • 对象里面的属性调用: 对象.属性名,这个小点. 就理解为“ 的”
  • 对象里面属性的另一种调用方式: 对象[‘属性名’],注意方括号里面的属性必须加引号,我们后面会用
  • 对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号
console.log(star.name) // 调用名字属性
console.log(star['name']) // 调用名字属性
star.sayHi(); // 调用sayHi 方法,注意,一定不要忘记带后面的括号

变量、属性、函数、方法总结

  • 变量:单独声明赋值,单独存在
  • 属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征
  • 函数:单独存在的,通过“函数名()”的方式就可以调用
  • 方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可以调用,方法用来描述该对象的行为和功能。

2.2 利用new Object创建对象

跟我们前面学的new Array() 原理一致(var arr = new Array()

var andy = new Obect();
andy.name = 'pink';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
     
    alert('大家好啊~');
}

Object() :第一个字母大写

new Object() :需要new 关键字

使用的格式:对象.属性= 值;

2.3 利用构造函数创建对象

构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面

在js 中,使用构造函数要时要注意以下两点:

  • 构造函数用于创建某一类对象,其首字母要大写
  • 函数内的属性和方法前面需要添加this ,表示当前对象的属性和方法。
  • 构造函数中不需要return 返回结果
  • 当我们创建对象的时候,必须用new 来调用构造函数
function Person(name, age, sex) {
     
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayHi = function() {
     
    	alert('我的名字叫:' + this.name + ',年龄:' + this.age + ',性别:' + this.sex);
    }
}
var bigbai = new Person('大白', 100, '男');
var smallbai = new Person('小白', 21, '男');
console.log(bigbai.name);
console.log(smallbai.name);

构造函数,如Person(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)

创建对象,如new Person(),特指某一个,通过new 关键字创建对象的过程我们也称为对象实例化

3. new 关键字

new 在执行时会做四件事情:

  1. 在内存中创建一个新的空对象。
  2. 让this 指向这个新的对象。
  3. 执行构造函数里面的代码,给这个新对象添加属性和方法。
  4. 返回这个新对象(所以构造函数里面不需要return)。

4. 遍历对象属性

for…in 语句用于对数组或者对象的属性进行循环操作。

其语法如下:

for (变量in 对象名字) {
	// 在此执行代码
}

语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为k 或者key

for (var k in obj) {
     
    console.log(k); // 这里的 k 是属性名
    console.log(obj[k]); // 这里的 obj[k] 是属性值
}

也可以遍历出方法名和方法,但是一般不常用

二、JavaScript 内置对象

1. 内置对象

JavaScript 中的对象分为3种:自定义对象、内置对象、浏览器对象

  • 前面两种对象是 JS 基础内容,属于ECMAScript;第三个浏览器对象属于我们 JS 独有的,我们 JS API 讲解
  • 内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)
  • 内置对象最大的优点就是帮助我们快速开发
  • JavaScript 提供了多个内置对象:Math、Date 、Array、String等

2. 查文档

学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查文档学习,可以通过MDN/W3C来查询。

Mozilla 开发者网络(MDN)提供了有关开放网络技术(Open Web)的信息,包括HTML、CSS 和万维网及HTML5 应用的API。

MDN: https://developer.mozilla.org/zh-CN/

如何学习对象中的方法:

  1. 查阅该方法的功能
  2. 查看里面参数的意义和类型
  3. 查看返回值的意义和类型
  4. 通过demo 进行测试

3. Math 对象

Math 对象不是构造函数,所以不需要new来调用,它具有数学常数和函数的属性和方法,我们可以直接使用即可。跟数学相关的运算(求绝对值,取整、最大值等)可以使用Math 中的成员。

Math.PI        // 圆周率
Math.floor()   // 向下取整
Math.ceil()    // 向上取整
Math.round()   // 四舍五入版就近取整   !!注意其他数字都是四舍五入,但是.5特殊,它是一直往大了取,例如Math.round(-3.5) = -3
Math.abs()     // 绝对值
Math.max()/Math.min() // 求最大和最小值

注意:上面的方法必须带括号

随机数方法random():random() 方法可以随机返回一个小数,其取值范围是[0,1),左闭右开0 <= x < 1

得到一个两数之间的随机整数,包括两个数在内,可以使用如下代码:

function getRandom(min, max) {
     
	return Math.floor(Math.random() * (max - min + 1)) + min;
} 

这个方法非常常用,写好了以后可以经常调用!

4. 日期对象

Date 实例用来处理日期和时间。Date 对象和Math 对象不一样,他是一个构造函数,所以我们需要实例化后才能使用。

var now = new Date();
console.log(now);

如果括号里面有时间,就返回参数里面的时间。例如日期格式字符串为 ‘2019-5-1’,可以写成 new Date(‘2019-5-1’) 或者new Date(‘2019/5/1’)。如果Date()不写参数,就返回系统当前时间

1. 日期格式化

一般默认输出格式为:Thu May 27 2021 21:47:13 GMT+0800 (中国标准时间),可读性比较差

我们想要2019-8-8 8:8:8 格式的日期,要怎么办?需要获取日期指定的部分,所以我们要手动的得到这种格式
3 JavaScript 对象与内置对象_第1张图片
请写出这个格式的日期:2019年8月8日星期四

var now = new Date('2019-8-8');
var year = now.getFullYear();
var month = now.getMonth() + 1;
var dates = now.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = now.getDay();
console.log('今天是' + year + '年' + month + '月' + dates + '日的' + arr[day]);

写一个函数,格式化日期对象,成为HH:mm:ss 的形式比如00:10:45

// 要求封装一个函数返回当前的时分秒 格式 08:08:08
function getTimer() {
     
    var time = new Date();
    var h = time.getHours();
    h = h < 10 ? '0' + h : h;
    var m = time.getMinutes();
    m = m < 10 ? '0' + m : m;
    var s = time.getSeconds();
    s = s < 10 ? '0' + s : s;
    return h + ':' + m + ':' + s;
}
console.log(getTimer());

2.获取日期的总的毫秒形式(时间戳)

Date 对象是基于1970年1月1日(世界标准时间)起的毫秒数,我们经常利用总的毫秒数来计算时间,因为它更精确

// 实例化Date对象
var now = new Date();
// 1. 用于获取对象的原始值
console.log(date.valueOf())
console.log(date.getTime())
// 2. 简单写可以这么做(最常用的方法)
var now = + new Date();
// 3. HTML5中提供的方法,有兼容性问题
var now = Date.now();

3. 案例:做一个倒计时效果(重要)
3 JavaScript 对象与内置对象_第2张图片

// 倒计时效果
// 1.核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。
// 2.用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
// 3.把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
// 转换公式如下: 
//  d = parseInt(总秒数/ 60/60 /24);    //  计算天数
//  h = parseInt(总秒数/ 60/60 %24)   //   计算小时
//  m = parseInt(总秒数 /60 %60 );     //   计算分数
//  s = parseInt(总秒数%60);            //   计算当前秒数
function countDown(time) {
     
    var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
    var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
    var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数 
    var d = parseInt(times / 60 / 60 / 24); // 天
    d = d < 10 ? '0' + d : d;
    var h = parseInt(times / 60 / 60 % 24); //时
    h = h < 10 ? '0' + h : h;
    var m = parseInt(times / 60 % 60); // 分
    m = m < 10 ? '0' + m : m;
    var s = parseInt(times % 60); // 当前的秒
    s = s < 10 ? '0' + s : s;
    return d + '天' + h + '时' + m + '分' + s + '秒';
}
console.log(countDown('2019-5-1 18:00:00'));
var date = new Date();
console.log(date);

5. 数组对象

创建数组对象的两种方式:字面量方式 和 new Array()

// 1. 利用数组字面量
var arr = [1, 2, 3];

// 2. 利用new Array()
// var arr1 = new Array();  // 创建了一个空的数组
// var arr1 = new Array(2);  // 这个2 表示 数组的长度为 2  里面有2个空的数组元素 
var arr1 = new Array(2, 3); // 等价于 [2,3]  这样写表示 里面有2个数组元素 是 2和3

5.1 检测是否为数组

  • instanceof 运算符,可以判断一个对象是否属于某种类型
  • Array.isArray()用于判断一个对象是否为数组,isArray() 是HTML5 中提供的方法, IE9以上版本才支持
var arr = [1, 23];
var obj = {
     };
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false

5.2 添加删除数组元素的方法

方法名 参数 返回值
push(参数1…) 末尾添加一个或多个元素,注意修改原数组 返回新的数组的长度
unshift(参数1…) 向数组的开头添加一个或多个元素,注意修改原数组 返回新的数组的长度
pop() 删除数组最后一个元素,把数组长度减1,无参数,修改原数组 返回它删除的元素的值
shift() 删除数组的第一个元素,数组长度减1,无参数,修改原数组 返回删除的元素的值

案例:有一个包含工资的数组[1500, 1200, 2000, 2100, 1800],要求把数组中工资超过2000的删除,剩余的放到新数组里面

var arr = [1500, 1200, 2000, 2100, 1800];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
     
    if (arr[i] < 2000) {
     
    	newArr.push(arr[i]);
    }
}
console.log(newArr);

5.3 数组排序

方法名 说明 是否修改原数组
reverse() 颠倒数组中元素的顺序,无参数 会改变原来的数组,返回新数组
sort() 对数组元素进行排序 会改变原来的数组,返回新数组
// 1. 翻转数组
var arr = ['pink', 'red', 'blue'];
arr.reverse();
console.log(arr);

// 2. 数组排序(冒泡排序)
var arr1 = [13, 4, 77, 1, 7];
arr1.sort(function(a, b) {
     
    //  return a - b; 升序的顺序排列
    return b - a; // 降序的顺序排列
});
console.log(arr1);

如果直接用arr1.sort(),返回结果是[1, 13, 4, 7, 77],是先按照第一位排,所以一般在实际开发中,都会使用参数(a,b)来进行排序

5.4 数组索引方法

方法名 说明 返回值
indexOf() 在数组中查找给定元素的第一个索引 如果存在则返回索引号,如果不存在就返回-1
lastIndexOf() 在数组中查找给定元素的最后一个索引 如果存在则返回索引号,如果不存在就返回-1

案例:数组去重(重点案例)

// 1.目标: 把旧数组里面不重复的元素选取出来放到新数组中, 重复的元素只保留一个, 放到新数组中去重。
// 2.核心算法: 我们遍历旧数组, 然后拿着旧数组元素去查询新数组, 如果该元素在新数组里面没有出现过, 我们就添加, 否则不添加。
// 3.我们怎么知道该元素没有存在? 利用 新数组.indexOf(数组元素) 如果返回时 - 1 就说明 新数组里面没有改元素
// 封装一个 去重的函数 unique 独一无二的 
function unique(arr) {
     
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
     
        if (newArr.indexOf(arr[i]) === -1) {
     
        newArr.push(arr[i]);
        }
    }
	return newArr;
}
// var demo = unique(['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'])
var demo = unique(['blue', 'green', 'blue'])
console.log(demo);

5.5 数组转换为字符串

方法名 说明 返回值
toString() 把数组转换成字符串,逗号分隔每一项 返回一个字符串
join(‘分隔符’) 按指定分隔符把数组分割成字符串,默认是逗号分隔 返回一个字符串

5.6 数组的其他方法

方法名 说明 返回值
concat() 用于合并两个或多个数组, 不会更改现有数组 返回一个新数组
slice() 数组截取slice(begin, end) 返回被截取项目的新数组
splice() 删除或替换现有元素或者原地添加新的元素来修改数组 返回被删除元素的新数组,注意,这个会影响原数组

slice() 和splice() 目的基本相同,重点看下splice()

array.splice(start, deleteCount[, item1[, item2[, ...]]]])
//start: 指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。
//deleteCount:整数,表示要移除的数组元素的个数。如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。
//从第 2 位开始删除 0 个元素,插入“drum”
var myFish = ["angel", "clown", "mandarin", "sturgeon"];
var removed = myFish.splice(2, 0, "drum");
// 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"]
// 被删除的元素: [], 没有元素被删除

//从第 3 位开始删除 1 个元素
var myFish = ['angel', 'clown', 'drum', 'mandarin', 'sturgeon'];
var removed = myFish.splice(3, 1);
// 运算后的 myFish: ["angel", "clown", "drum", "sturgeon"]
// 被删除的元素: ["mandarin"]

//从第 0 位开始删除 2 个元素,插入"parrot"、"anemone"和"blue"
var myFish = ['angel', 'clown', 'trumpet', 'sturgeon'];
var removed = myFish.splice(0, 2, 'parrot', 'anemone', 'blue');
// 运算后的 myFish: ["parrot", "anemone", "blue", "trumpet", "sturgeon"]
// 被删除的元素: ["angel", "clown"]

6. 字符串对象

6.1 基本包装类型

为了方便操作基本数据类型,JavaScript 还提供了三个特殊的引用类型:String、Number和Boolean。基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。

// 下面代码有什么问题?
var str = 'andy';
console.log(str.length);

按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为js 会把基本数据类型包装为复杂数据类型,其执行过程如下:

// 1. 生成临时变量,把简单类型包装为复杂数据类型
var temp = new String('andy');
// 2. 赋值给我们声明的字符变量
str = temp;
// 3. 销毁临时变量
temp = null;

6.2 字符串的不可变

指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间

var str = 'abc';
str = 'hello';
// 当重新给str 赋值的时候,常量'abc'不会被修改,依然在内存中
// 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
// 由于字符串的不可变,在大量拼接字符串的时候会有效率问题
var str = '';
for (var i = 0; i < 100000; i++) {
     
	str += i;
}
console.log(str); // 这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间

6.3 根据字符返回位置

字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。

方法名 说明
indexOf(‘要查找的字符’,开始的位置) 返回指定内容在字符串中的位置,如果找不到就返回-1,开始的位置是index索引号,表示从哪个位置开始查找
lastIndexOf() 从后往前找,只找第一个匹配的

案例:查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数(重点!)

// 核心算法:先查找第一个o出现的位置
// 然后 只要indexOf 返回的结果不是 -1 就继续往后查找
// 因为indexOf 只能查找到第一个,所以后面的查找,一定是当前索引加1,从而继续查找
var str = "oabcoefoxyozzopp";
var index = str.indexOf('o');
var num = 0;
while (index !== -1) {
     
    console.log(index);
    num++;
    index = str.indexOf('o', index + 1);
}
console.log('o出现的次数是: ' + num);

针对数组[‘red’, ‘blue’, ‘red’, ‘green’, ‘pink’,‘red’], 求 red 出现的位置和次数,和上述方法是一样的!

6.4 根据位置返回字符(重点)

方法名 说明 使用
charAt(index) 返回指定位置的字符 str.charAt(0);
charCodeAt(index) 返回指定位置的字符的ASCII码 str.charCodeAt(0);
str[index] 获取指定位置处字符 HTML5,IE8+支持 和charAt等效

案例:判断一个字符串’abcoefoxyozzopp’ 中出现次数最多的字符,并统计其次数。

// 有一个对象 来判断是否有该属性 对象['属性名']
var o = {
     
    age: 18
}
if (o['sex']) {
     
    console.log('里面有该属性');
} else {
     
    console.log('没有该属性');
}

//  判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数。
// o.a = 1
// o.b = 1
// o.c = 1
// o.o = 4
// 核心算法:利用 charAt() 遍历这个字符串
// 把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1
// 遍历对象,得到最大值和该字符
var str = 'abcoefoxyozzopp';
//创建一个新的对象o,chars表示属性,出现次数表示对应的属性值
var o = {
     }; 
for (var i = 0; i < str.length; i++) {
     
    var chars = str.charAt(i); // chars 是 字符串的每一个字符
    if (o[chars]) {
      // o[chars] 得到的是属性值
    	o[chars]++;
    } else {
     
    	o[chars] = 1;
    }
}
console.log(o);
// 2. 遍历对象
var max = 0;
var ch = '';
for (var k in o) {
     
    // k 得到是 属性名
    // o[k] 得到的是属性值
    if (o[k] > max) {
     
        max = o[k];
        ch = k;
    }
}
console.log(max);
console.log('最多的字符是' + ch);

6.5 字符串操作方法(重点)

方法 说明
concat(str1, str2…) concat()方法用于连接两个或多个字符串,拼接字符串,等效于+,+更常用
substr(start, length) 从start位置开始(索引号),length取的个数,重点记住这个
slice(start, end) 从start位置开始,截取到end位置[start, end)
substring(start, end) 从start位置开始,截取到end位置[start, end),和上述相同,但是不接受负值

6.6 replace()方法

replace() 方法用于在字符串中用一些字符替换另一些字符。其使用格式如下:

replace(被替换的字符串,要替换为的字符串);

注意:当有多个相同字符时,该式只能替换第一个字符

// 1. 替换字符 replace('被替换的字符', '替换为的字符')  它只会替换第一个字符
var str = 'andyandy';
console.log(str.replace('a', 'b'));
// 有一个字符串 'abcoefoxyozzopp'  要求把里面所有的 o 替换为 *
var str1 = 'abcoefoxyozzopp';
while (str1.indexOf('o') !== -1) {
     
	str1 = str1.replace('o', '*');
}
console.log(str1);

6.7 split()方法

split()方法用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。例如下面代码:

var str = 'a,b,c,d';
console.log(str.split(',')); // 返回的是一个数组[a, b, c, d]
  • toUpperCase() //转换大写,返回一个新的字符串,表示转换为大写的调用字符串
  • toLowerCase() //转换小写,返回一个新的字符串,表示转换为小写的调用字符串

三、JavaScript 简单类型与复杂类型

1. 简单类型与复杂类型

简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。

  • 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型。例如:string ,number,boolean,undefined,null(比较特殊,返回的是空对象Object,如果有个变量我们以后打算存储为对象,暂时没想好放啥, 这个时候就给 null )
  • 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型。通过new 关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等

2. 堆和栈

堆栈空间分配区别:
  1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
  2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面

注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。

简单类型的内存分配

值类型(简单数据类型):string ,number,boolean,undefined,null

值类型变量的数据直接存放在变量(栈空间)中

3 JavaScript 对象与内置对象_第3张图片

复杂类型的内存分配

引用类型(复杂数据类型):通过new 关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等

引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
3 JavaScript 对象与内置对象_第4张图片

3. 简单类型与复杂类型传参

简单类型传参(值传递)

函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到外部变量。

function fn(a) {
     
    a++;
    console.log(a);
}
var x = 10;
fn(x);
console.log(x)

复杂类型传参(引用传递)

函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。

function Person(name) {
     
    this.name = name;
}
function f1(x) {
      // x = p
    console.log(x.name); // 2. 这个输出什么? 刘德华
    x.name = "张学友";
    console.log(x.name); // 3. 这个输出什么? 张学友
}
var p = new Person("刘德华");
console.log(p.name); // 1. 这个输出什么?  刘德华
f1(p);
console.log(p.name); // 4. 这个输出什么?  张学友

你可能感兴趣的:(前端学习笔记,javascript,字符串)