JavaScript学习笔记

2021-02-09   2,579 次阅读


请注意,本文编写于  128  天前,最后编辑于  128  天前,内容可能已经不具有时效性,请谨慎参考。

基础语法

注释

  1. //
  2. /* ... */

数据类型

  1. Number
  2. 字符串
  3. 布尔值
    1. 与运算:&&
    2. 或运算:||
    3. 非运算:!
    4. 比较运算符
      1. ==比较,它会自动转换数据类型再比较
      2. ===比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。
      3. NaN这个特殊的Number与所有其他值都不相等,包括它自己(可以使用isNaN()函数进行判断)
      4. null and undefine
  4. 数组
    1. [element_a,element_b,element_c]
    2. New Array(element_a,element_b,element_c) //创建数组同a
  5. 对象
var person = {
    name: 'Bob',
    age: 20,
    tags: ['js', 'web', 'mobile'],
    city: 'Beijing',
    hasCar: true,
    zipcode: null
};

获取一个对象的属性,我们用对象变量.属性名的方法

变量

  1. var
  2. strict模式(强制通过var申请变量,未使用则报错)

字符串

  1. 使用 \ 进行转义
  2. \x## 使用十六进制asciii
  3. \u#### 使用unicode
  4. 多行字符串
`这是一个
多行
字符串`;
  1. 模版字符串
    1. 使用 + 进行连接
    2. 使用$引用变量(需要使用反引号进行引用)
  2. 字符串的常用操作
    1. str.length ->获取长度
    2. str[number]->进行取出
    3. str.toUpperCase()->全部转成大写字符串
    4. str.toLowerCase()->全部转成小写字符串
    5. str.indexOf('word')->搜索指定字符串出现的位置,没找到则返回-1
    6. str.substring(0,5)->返回索引区间在[0,5)的字符串,str.substring(7)->索引7开始到结束

数组

  1. array.length->获取长度(可以对其赋值而改变长度,未定义则)
  2. array.indexOf()->搜索指定元素的位置,没有则返回-1
  3. slice()->同substring同样的用法(若不指定参数,则从头到尾截断,利用这一个特点可以深拷贝一个新的数组
  4. push()、pop()->从尾部添加、返回删除元素(空组继续pop返回undefined)
  5. unshift()、shift()->从首部添加、返回删除的元素(空组返回undefined)
  6. sort()->排序
  7. reverse()->反转数组
  8. splice(start_index,number,add_element1,add_element2)->返回删除的元素并添加新元素

splice(start_index,number)->只返回删除的元素

splice(start_index,0,add_emelemt1,add_element2)->只添加元素,返回[]

  1. array_1.concat(array_2)->合并两个数组
  2. array.join('str')->在每两个元素之间添加str

对象

var object = {
    name: '小明',
    birth: 1990,
    school: 'No.1 Middle School',
    height: 1.70,
    weight: 65,
    score: null
};
  1. 使用object.key->得到value
  2. 使用object[key]取出值
  3. 访问属性是通过.操作符完成的,但这要求属性名必须是一个有效的变量名。如果属性名包含特殊字符,就必须用''括起来
var object = {
    name: '小红',
    'middle-school': 'No.1 Middle School'
};

如上,取出middle-school的时候需要使用object['middle-school']

  1. 访问不存在的key时,返回undefined
  2. 直接使用object.key=value / object[key] = value 进行添加,同时可以使用delete进行删除
  3. 'key' in object 可以判断是否存在对应的key
  4. 要判断一个属性是否是 object 自身拥有的,而不是继承得到的,可以用hasOwnProperty('key')方法

条件判断

if else if else{};

循环

  1. for( A; B; C)
  2. for(... in ...) -> 对于array类型的可以看作key为索引
  3. for(... of ...)
  4. while
  5. do while

Map & Set(ES6)

  1. 使用 new Map() / new Set()进行创建
  2. Map: set(key,value)、has(key)、get(key)、delete(key)
  3. Set: 不重复的集合add(key)、 delete(key)

iterable

使用 for ... of ...进行可迭代对象遍历。

forEach方法,接收一个函数,每次迭代就自动回调该函数

函数

  1. 定义函数与调用
    1. function xxx(x,y,z)
    2. var func_name = function (x);
    3. arguments->获取目前函数传入的所有
  2. 变量提升,js会提升声明,但不会提升赋值。
  3. 全局作用域:绑定到window的一个属性上
  4. 名字空间
  5. 局部作用域
  6. let替代var可以申请一个块级作用域
  7. 常量:const
  8. 解构赋值: var [x,y,z] = [a,b,c],

在对象中,如果要使用的变量名和属性名不一致可以使用old_key:new_key进行表达

  1. 解构时可以设置默认值,也可以跳过

方法

  1. 可以为对象的绑定一个函数(绑定到对象的函数称之为方法)
  2. this函数总是指向当前对象
  3. 特殊用法

img

  1. apply ->控制this的指向

func.apply(需要绑定this的变量,array表示函数本身需要传入的参数)

function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};

xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空
  1. apply 和 call 区别:apply是将参数打包array传入,call把参数按照顺序传入。
  2. 装饰器:
    1. 封存原函数
    2. 使用window修改现函数,添加计数函数
    3. 返回 利用apply实现原函数的调用

高阶函数

高阶函数实际上就是接收另一个函数作为参数的函数。

  1. map:接收一个函数,将该函数逐个作用到可迭代对象上 iterable.map(function)
  2. reduce:接受一个函数,且该函数必须接收两个参数。将结果继续和序列的下一个元素进行计算。

attention:

map方法的函数只要一个参数,但是map传递的参数有三个,分别是:数组元素、元素索引,数组本身,而paresInt是可以接受两个参数的,第一个是字符,第二个是进制。

['1', '2', '3'].map(paresInt)

相当于

['1', '2', '3'].map(paresInt(value, index))

执行的内在逻辑就是:

第一个元素就是:paresInt('1', 0) > 1

第二个元素就是:paresInt('2', 1) > NaN

第三个元素就是:paresInt('3', 2) > NaN

  1. filter:类似map的使用,将函数作用到可迭代对象中,返回函数判断为真的元素

回调函数:filter(function(element,index,self)) 通常我们仅使用第一个参数,表示Array的某个元素。回调函数还可以接收另外两个参数,表示元素的位置和数组本身。

  1. sort:在JS中是将元素转换成string后进行排序(大坑),不过sort可以接收一个函数进行排序
  2. Array:
    1. every():判断数组元素是不是都满足测试条件
    2. find():查找符合条件的第一个元素
    3. findIndex():返回符合条件的第一个元素的索引值
    4. forEach():用于遍历可迭代对象

闭包

把函数作为一个返回值称之为闭包,其内部局部变量还引用外部变量(重点)

tips:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

匿名函数

例子1:(function(x){ return x*x; })(3);

例子2:

(function(x){

return x*x;

})(3);

箭头函数

Arrow function: 类似于匿名函数

x =>x*x

相当于

function(x){

return x*x;

}

对于多条语句的箭头函数,使用以下形式

x => {

... 且必须包含return语句...

}

两个参数则需要使用括号包含

(x,y) => x+y;

生成器

function* (x,y,z){

yield x;

yield y;

return z;}

可以使用next()或者for ... of ... 进行循环迭代

标准对象

  1. 在JS中所有都是对象,使用typeof得到个对象的类型返回的字符串如下

img

  1. 包装对象

number、boolean、string都有包装对象,可以用new进行创建。并且创建出来的值虽然一模一样但是类型却变成了object,所有用===进行判断是会返回false

  1. 总结:
  • 不要使用new Number()、new Boolean()、new String()创建包装对象;
  • 用parseInt()或parseFloat()来转换任意类型到number;
  • 用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;
  • 通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar)
  • typeof操作符可以判断出number、boolean、string、function和undefined;
  • 判断Array要使用Array.isArray(arr);
  • 判断null请使用myVar === null;
  • 判断某个全局变量是否存在用typeof window.myVar === 'undefined';
  • 函数内部判断某个变量是否存在用typeof myVar === 'undefined'

tips:整形使用toString()方法时,需要按照如下使用:

123..toString() 或者 (123).toString()

Date

  1. 创建一个指定日期:new Date(2020,11,25,12,0,0,0); JavaScript的月份范围用整数表示是0~11
  2. Date.parse('2020-05-15T19:01:05.123+08:00');转换成时间戳格式

RegExp

  1. 正则表达式:
\d:匹配一个数字\w:匹配一个字母或数字. :匹配任意一个字符
*:匹配0个或者多个+:匹配至少1个?:匹配0个或者1个
\s:匹配一个空白符{m,n}:表示匹配m-n个特殊字符:使用 \ 转义
[0-9a-zA-Z]:进行匹配^:表示开头$:表示结尾
  1. JS中两种正则的写法
    1. 使用两个斜杠包裹住 re1 = / string /
    2. re2 = new Reg(' string ')

使用方法是 RegExp对象.test(待匹配字符串)

  1. 切分字符串:split(正则)
  2. 分组:将正则的规则使用括号分组,进行匹配时会将匹配到的分组进行提取。如果正则表达式中定义了组,就可以在RegExp对象上用exec()方法提取出子串来。
  3. 贪婪匹配:就是会优先匹配尽可能多的子序列,使用 +?组合进行非贪婪匹配。
  4. 全局搜索:

JavaScript的正则表达式还有几个特殊的标志,最常用的是g,表示全局匹配:

var r1 = /test/g;
// 等价于:
var r2 = new RegExp('test', 'g');

当我们指定g标志后,每次运行exec(),正则表达式本身会更新lastIndex属性,表示上次匹配到的最后索引:

JSON

JSON的字符串规定必须用双引号"",Object的键也必须用双引号""

  1. 序列化:将对象转换成json:JSON.stringify(object_name[,function,'格式'])
  2. 反序列化:将json转换成对象:JSON.parse(json,[function])

面向对象编程

JS不通过类和实例的概念,而通过原型来实现面向对象编程。

JS中所有对象都是一个实例,所谓的继承关系不过是从一个对象指向另一个对象。

  1. obj.proto = other_obj;(不要直接用)
  2. var new_obj = Object.create(old_obj);
  3. var new_obj = new Object(old_obj);

创建对象

使用new进行创建新对象。如果不写new就是一个普通的函数。

function obj_student(name){
    this.name = name;
    this.hello = function(){
        alert('hello ' + this.name);
    };
}

var new_stu = new obj_student('hcy');

原型链:new_stu-->obj_student.prototype-->Object.prototype-->null

要让创建的对象共享一个函数,可以通过将函数移动到新对象共同的原型上(obj_student.prototype上即可)

obj_student.prototype.hello = function(){...};

原型继承

  1. 定义新的构造函数,并在内部用call()调用希望“继承”的构造函数,并绑定this;
  2. 借助中间函数F实现原型链继承,最好通过封装的inherits函数完成;
  3. 继续在新的构造函数的原型上定义新方法。

class继承

  1. class

回顾用函数实现Student的方法:

function Student(name) {
    this.name = name;
}

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
}

用新的class关键字实现如下:

class Student{
    constructor(name){
        this.name = name;
        }
    hello(){
        alert('hello,' + this.name +'!');
        }
}

class定义包含了构造函数constructor和定义在原型对象上的函数(不需要function),最后创建一个student对象代码和前面一样。

var new_obj = new Student('robot');
new_obj.hello();
  1. class继承
class primaryStudent extends Student{
    constructor(name,grade){
        super(name);//用super调用父类构造方法
        this.grade = grade;
    }
    myGrade(){
        console.log(this.grade);
    }
}

Extends 则表示原型链对象来自Student。 子类的构造函数可能不一样。例如primaryStudent需要name和grade,并且需要super(name)来调用父类的构造函数,否则父类name属性无法正常初始化。

Window

window对象不仅充当全局作用域,而且表示浏览器窗口。可以使用innerWidth 和innerHeight两个属性来获取页面的净宽高。使用outerWidth和outerHeight来获取整个浏览器窗口的宽高。

表示浏览器的信息,属性包括:

  • navigator.appName:浏览器名称;
  • navigator.appVersion:浏览器版本;
  • navigator.language:浏览器设置的语言;
  • navigator.platform:操作系统类型;
  • navigator.userAgent:浏览器设定的User-Agent字符串。

Screen

表示屏幕的信息,属性包括:

  • screen.width:屏幕宽度,以像素为单位;
  • screen.height:屏幕高度,以像素为单位;
  • screen.colorDepth:返回颜色位数,如8、16、24。

Location

表示当前页面的URL信息。

location.href;  //http://www.example.com:8080/path/index.html?a=1&b=2#TOP
location.protocol; // 'http'
location.host; // 'www.example.com'
location.port; // '8080'
location.pathname; // '/path/index.html'
location.search; // '?a=1&b=2'
location.hash; // 'TOP'

可以使用location.assign()加载一个新的页面,location.reload()重新加载当前页面。

Document

表示当前页面,HTML在浏览器以DOM表示为树形结构,document相当于DOM树的根节点。

可使用getElementById() / getElementByTagName()按照ID/Tag Name获取一组节点。

使用document.cookie;可以获取当前的页面的cookie,服务器在设置Cookie时可以使用httpOnly,设定了httpOnly的Cookie将不能被JavaScript读取。这个行为由浏览器实现,主流浏览器均支持httpOnly选项。

history

保存浏览器的历史记录,可以调用back() / forward()相当于后退和前进。(不适用)

操作DOM

  1. 由于ID在HTML文档中是唯一的,所以document.getElementById()可以直接定位唯一的一个DOM节点。document.getElementsByTagName()和document.getElementsByClassName()总是返回一组DOM节点。要精确地选择DOM,可以先定位父节点,再从父节点开始选择,以缩小范围。
  2. 使用querySelector()和querySelectorAll(),需要了解selector语法,然后使用条件来获取节点

更新DOM

  1. 修改innerHTML
  2. 修改innerText或者textContent (innerText不返回隐藏元素的文本,而textContent返回所有文本。另外注意IE<9不支持textContent)

插入DOM

  1. parent_Element.appendChild()
  2. parent_Element.insertBefore(new_Element,referenceElement),子节点会插入到referenceElement之前

删除DOM

  1. parten.removeChild(children)

操作表单

< input type= "xxx">其中xxx分为text/password/radio/checkbox/hidden代表文本/口令/单选/多选/隐藏文本。< select>下拉框。

获取值/设置值:可以直接调用value获取对应的用户输入值。但是对于单选/复选返回的属性永远是HTML的预设值,要获取实际的用户选项需要使用checked判断。

控件

HTML5新增了大量标准控件,常用的包括date、datetime、datetime-local、color等,它们都使用< input>标签

提交表单

  1. 通过
    元素的submit()方法提交一个表单。
  2. 响应的onsubmit
<!-- HTML -->
<form id="test-form" onsubmit="return checkForm()">
    <input type="text" name="test">
    <button type="submit">Submit</button>
</form>

<script>
function checkForm() {
    var form = document.getElementById('test-form');
    // 可以在此修改form的input...
    // 继续下一步:
    return true;
}
</script>
  1. 没有name属性的< input>的数据不会被提交

操作文件

HTML中唯一可以上传的控件是< input type = "file">,在包含上传控件时表单enctype必须指定为multipart/form-data,method必须指定为post,浏览器才能正常编码。

tips:JS无法修改type="file"的value赋值。

File API

File和FileReader两个对象,可以获取文件信息并且读取文件

回调

JS中执行代码总是以单线程模式执行的,处理多任务时是以异步调用的形式执行的。

比如上面的代码:

reader.readAsDataURL(file);

就会发起一个异步操作来读取文件内容。因为是异步操作,所以我们在JavaScript代码中就不知道什么时候操作结束,因此需要先设置一个回调函数:

reader.onload = function(e) {
    // 当文件读取完成后,自动调用此函数:
};

当文件读取完成后,JavaScript引擎将自动调用我们设置的回调函数。执行回调函数时,文件已经读取完毕,所以我们可以在回调函数内部安全地获得文件内容。

AJAX

  1. 依赖XMLHttpRequest对象进行写AJAX。
  2. 安全限制:URL使用相对路径,因为AJAX请求时,必须和当前页面完全一致(域名相同、端口相同、协议相同)
  3. CORS:跨域资源策略。假设本域是 my.com,外域是 sina.com,只要响应头Access-Control-Allow-Origin为http://my.com,或者是*,本次请求就可以成功。

Promise

Promise().then().then....catch() 多任务串行执行.

情景化记忆:在一个任务链中,比如我要向上级部门一层层的往上提交申请,if(某种条件)承诺帮你resolve解决问题,else承诺reject你的请求. 他给出的resolve问题的办法只是个空头Promise,then到总经理那实现具体承诺,如果总经理还是给一个空头承诺(返回Promise实例),还得then到董事长那里.... 任一一步做出的是reject的承诺,还有什么好说的,被拒绝了,后面的就不会再往上走了呀. 准备catch 拒绝通知吧blablabla

Promise.all([p1,p2,...]) 多任务并行执行

都要成功才进入then,返回结果数组.

Promise.race([p1,p2,...]) 多任务赛跑.

then()和catch(),谁先调用算谁的,其它任务中断.

Canvas

...

jQuery

  1. 消除浏览器差异
  2. 简洁操作DOM
  3. 轻松实现动画以及修改CSS等操作

$:变量JQuery的别名,本质上就是一个函数,但函数也是对象,于是$除了可以直接调用以外还能有其他很多属性。

选择器

  1. 按ID查找:
// <div id = "abc">
var id_ = $('#abc'); 

需要以#开头,返回的是一个jQuery对象。不存在则返回 [ ]

  1. 按tag查找:

只需要写上tag名称就可以了。

var ps = $('p');     //返回所有<p>节点
ps.length;    //返回<p>节点数
  1. 按class查找:

需要在class名称之前加一个**.**

var a = $('.red');    //所有节点包含class="red"都将被返回
// 例如:
// <div class="red">...</div>
// <p class="green red">...</p>
  1. 按属性查找

一个DOM有许多属性可以查找,如:

var email = $('[name=email]');    //找出 <??? name="email">
var pwd = $('[type=password]');    //找出<??? type="password>
var a = $('[item="A B"]');        //找出<??? items="A B">

当属性的值包含空格等特殊字符时,需要用双引号括起来

还可以使用前后缀查找:

var icons = $('[name^=icon]');    //找出所有name属性值以icon开头的DOM
var names = $('[name$=with]');    //找出所有name属性值以with结尾的DOM
var icons = $('[class^="icon-"]');    //找出所有class包含至少一个以icon-开头的DOM
  1. 组合查找
var a = $('input[name=email]');    //只查找<input>中符合条件的
//class 同理
  1. 多项选择器

把多选器用,组合起来一块选。

$('p,div');    //把<p>和<div>都选出来

层级选择器

如果两个DOM元素具有层级关系,就可以使用$('ancestor descendant')来选择,层级之间用空格隔开。

<!-- HTML结构 -->
<div class="testing">
    <ul class="lang">
        <li class="lang-javascript">JavaScript</li>
        <li class="lang-python">Python</li>
        <li class="lang-lua">Lua</li>
    </ul>
</div>

要选出JavaScript,可以用层级选择器:

$('ul.lang li.lang-javascript'); // [<li class="lang-javascript">JavaScript</li>]
$('div.testing li.lang-javascript'); // [<li class="lang-javascript">JavaScript</li>]

因为

    都是
  • 的祖先节点,所以上面两种方式都可以选出相应的
  • 节点。

    要选择所有的

  • 节点,用:

    $('ul.lang li');
    

    子选择器

    子选择器$('parent>child')类似层级选择器,但是限定了关系必须是父子关系。

    过滤器

    通常附加在选择器上帮助更精确地定位元素

    $('ul.lang li'); // 选出JavaScript、Python和Lua 3个节点
    
    $('ul.lang li:first-child'); // 仅选出JavaScript
    $('ul.lang li:last-child'); // 仅选出Lua
    $('ul.lang li:nth-child(2)'); // 选出第N个元素,N从1开始
    $('ul.lang li:nth-child(even)'); // 选出序号为偶数的元素
    $('ul.lang li:nth-child(odd)'); // 选出序号为奇数的元素
    

    表单相关

    针对表单元素,jQuery还有一组特殊的选择器:

    • :input:可以选择< input>,< textarea>, < select>和< button>;
    • :file:可以选择< input type="file">,和input[type=file]一样;
    • :checkbox:可以选择复选框,和input[type=checkbox]一样;
    • :radio:可以选择单选框,和input[type=radio]一样;
    • :focus:可以选择当前输入焦点的元素,例如把光标放到一个< input>上,用$('input:focus')就可以选出;
    • :checked:选择当前勾上的单选框和复选框,用这个选择器可以立刻获得用户选择的项目,如$('input[type=radio]:checked');
    • :enabled:可以选择可以正常输入的< input>、< select> 等,也就是没有灰掉的输入;
    • :disabled:和:enabled正好相反,选择那些不能输入的。

    此外,jQuery还有很多有用的选择器,例如,选出可见的或隐藏的元素:

    $('div:visible'); // 所有可见的div
    $('div:hidden'); // 所有隐藏的div
    

本文由 hongCYu 创作,如果您觉得本文不错,请随意赞赏
采用 知识共享署名4.0 国际许可协议进行许可
原文链接:https://hongcyu.cn/posts/javascript.html
最后更新于:2021-02-09 20:22:03

Coffee