写作不易,Star是最大鼓励,感觉写的不错的可以给个Star⭐,请多多指教。Github地址

对象

什么是对象?

  • 面向对象编程中最重要的就是对象,万物皆对象
  • 一个对象代表现实中的某个事物,是该事物在编程中的抽象
  • 多个数据的封装体(而每个变量只能保存一个数据)
  • 用来保存多个数据的容器

为什么要用对象?

  • 集中管理多个数据
  • 便于对多个数据进行统一管理

对象的组成

  • 属性
    • 代表现实事物的状态数据
    • 由属性名和属性值组成
    • 属性名都是字符串类型,属性值可以是任意类型
  • 方法
    • 代表现实事物的行为数据
    • 一种特殊属性(属性值是函数)

如何访问对象内部数据

  • dot(.)属性名:编码简单,但是有些场景下不能用
  • ['属性名']:编码麻烦,但是任何场景都通用

如何让变量称为垃圾对象进而被垃圾回收机制回收?

变量名 = null;
1

什么时候必须使用['属性名']的方式?

  1. 当属性名中包含特殊字符:-、空格;
  2. 属性名是不确定的变量。
var p = {};
// 给p对象添加一个属性名:content-type: text/json
// p.content-type = 'text/json'; // 不能用
p['content-type'] = 'text/json';
1
2
3
4
var obj = {};
// 变量名不确定
var name = 'myName';

obj[name] = 'lisi';
obj.name = 'sss'; // .的方式是直接添加了name属性而不是myName
console.log(obj); // { myName: 'lisi', name: 'sss' }
1
2
3
4
5
6
7

函数

什么是函数?

  • 函数也是对象
  • 实现特定功能的n条语句的封装体
  • 只有函数是可以执行的,其他类型的数据不能执行的

为什么要用函数?

  • 提高代码复用
  • 便于阅读交流

如何定义函数(定义函数的方法)

  • 函数声明:存在函数声明提升
  • 函数表达式:不存在函数声明提升
  • 构造函数
  1. 函数声明
// ES5
function fn(){}
function (){}//匿名函数
// ES6
() => {}
1
2
3
4
5
  1. 函数表达式
// ES5
var fn = function(){}
// ES6
let fn = () => {}
1
2
3
4
  1. 构造函数
const fn = new Function('a', 'b' , 'return a + b')
1

如何调用函数

  • test():直接调用
  • obj.test():通过对象调用
  • new Person():new调用(构造函数)
  • test.call/apply(obj):可以让一个函数成为指定任意对象的方法进行调用,临时让test成为obj的方法进行调用

回调函数

什么函数才是回调函数

满足3个特点:

  • 已经定义了
  • 但是没有直接调用
  • 最终函数执行了(在某个时刻或者某种条件下执行了)

常见的回调函数

  • dom事件回调函数:this指向发生事件的dom元素
  • 定时器回调函数
  • ajax请求回调函数
  • 生命周期回调函数
document.getElementById('btn').onclick = function () {
  alert('回调函数执行');
};
setTimeout(function () {
  alert('定时器回调函数执行');
}, 2000);
1
2
3
4
5
6

回调函数this指向

  • dom事件回调函数:this指向发生事件的dom元素
  • 定时器回调函数:this指向window

IIFE(Immediately-Invoked Function Expression)

MDN中这样定义:IIFE(立即调用函数表达式)是一个在定义时就会立即执行的JavaScript函数,又称为匿名函数自执行。

特点:

  1. 代码被加载立即执行
  2. 内部的数据是私有的
(function () {
  console.log('立即执行函数');
})()
1
2
3

作用:

  1. 隐藏内部实现
  2. 不污染外部(全局)命名空间
(function(){ // 匿名函数自调用
    var a = 3;
    console.log(a);
})()

;(function() {
    var a = 1;
    function test() {
        console.log(++a);
    }
    window.$ = function() { // 向外暴露一个全局函数
        return {test};
    }
})();

console.log($().test());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在javascript中任何匿名函数都是属于window对象。在定义匿名函数时候它会返回自己的内存地址,如果此时有个变量接收了这个内存地址,那么匿名函数就能在程序里被使用了(可以通过在这个变量后面加一对圆括号来调用这个匿名函数),因为匿名函数也是在全局执行环境构造时候定义和赋值,所以匿名函数的this指向也是window对象。

(function(){
	console.log(this == window); //true
})();
1
2
3

参数传递

function test(num) { // 按值传递
     num+=5;
     console.log(num);
     return num;
 }
 var num = 5;
 var result = test(num);
 console.log(result); // 10 如果是按引用传递,那么函数里的num会成为类似全局变量,把外面的num覆盖掉
 console.log(num); // 5 也就是说,最后应该输出20(这里输出10)
1
2
3
4
5
6
7
8
9

js中不存在引用传递,如果存在引用传递的话,那么函数内的变量将是全局变量,在外部也可以访问,但这明显是不可能的。

再来看个🌰:

function setName(obj){ //obj = person
	obj.name = "lisi";
	obj = new Object();
	obj.name = "wangwu";
}
var person = new Object();
setName(person);
alert(person.name);
console.log(obj.name);//Uncaught ReferenceError: obj is not defined
1
2
3
4
5
6
7
8
9

在将person传递给obj后,其name属性就被设置成了"lisi"。又将obj重新定义了一个对象,另一行代码为该对象定义了一个带有不同值的name属性。

如果person是按引用传递的,那么person就会自动被修改为指向其name属性值为"wangwu"的新对象,但事实上并没有,其name属性依然是"lisi"。

**这就说明:**即使在函数内部修改了参数的值,但原始的引用仍然保持不变。实际上,当在函数内重写obj时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。