JavaScript视频课程笔记【入门到精通】,这只是笔记!!!
主要内容:
解析器在调用函数时,每次都会向函数内部传递一个隐含参数,这个隐含参数就是this
function sayName(){
console.log(this);
}
sayName();//this->window
var obj = {
name:'hahah',
sayName:sayName
}
obj.sayName();//this->obj
算是个技巧吧;
都使用了Object的构造函数,返回的对象类型 都是Object类型;
function createObj(name,age,opre){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.opre = opre;
obj.sayName = function(){
console.log(this.name);
}
return obj;
}
构造函数其实就是一个普通的函数,习惯上首字母需要大写;
与普通函数 区别在于 构造函数 需要使用 new来调用;
function Person(){
}
function Dog(){
}
var person = new Person();
var dog = new Dog();
构造函数执行流程:
因此 在构造函数中,可以使用this引用新创建的对象;
function Person(name){
this.name = name || '猴哥';
}
可以使用instanceof运算符判断实例类型:
var per1 = new Person();
per1 instanceof Person;//true
per1 instanceof Object;//true
所有实例都是Object类的实例;
对象打印时,除了函数会打印function,其他嗾使object;
为多个对象指定公共函数的问题:
将函数定义在全局作用域,污染了全局作用域的命名空间,而且定义在全局作用域中也很不安全,再起重名函数,易被覆盖;通过这个问题引出原型对象;
在我们所创建的每一个函数时,解析器都会向函数中添加一个属性prototyoe,无论是构造函数还是普通函数;这个属性对应着是一个对象,这个对象就是我们所谓的原型对象;
function Person(){
}
console.log(Person.prototype)
new Person()
),它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象;这个隐含属性可以通过 __proto__
来访问(只是访问);function MyClass(){
}
var mc = new MyClass();
var mc2 = new MyClass();
mc.__proto__ == MyClass.prototype//true
mc2.__proto__ == MyClass.prototype//true
相当于一个公共区域,所有同一个类的实例都可以访问这个原型对象;
可以将对象共有的内容,统一设置到原型对象中;
MyClass.prototype.a = 123;
mc.a;//123
共有的函数也可以放在原型对象中,这样就不会出现本节一开始函数定义在全局的问题了;
以后创建构造函数时,可以将这些对象的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了;
hasOwnProperty()
方法来检查对象自身是否包含指定属性;// 只有对象自身中含有该属性时,才会返回true
console.log(mc.hasOwnProperty("age"));
console.log(mc.hasOwnProperty("hasOwnProperty"));//false
console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));//false
// ...
console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));//true
根原型对象是Object,Object对象没有原型,如果在Object中依然没有找到需要的属性,则返回undefined;
原型链对应着面向对象类的继承链;
function Person(name,age,gender){
this.name = name;
this.age = age;
this.gender = gender;
}
var per = new Person("猴哥",18,'boy');
console.log(per);// [object Object]
这里打印per对象,实际输出的是对象的toString()方法 的返回值;之所以打印出了“[object Object]”就是因为toString()方法的返回值就是“[object Object]”;
toString()方法定义在Object类中,如果希望实际输出的不是默认的,就可以为对象的原型
添加一个toString方法:
Person.prototype.toString = function(){
return this.name + this.age + this.gender;
}
对象的原型对象 指向 类的原型对象,类的原型对象指向其原型对象的原型对象,如Object(表现为类之间的继承链),Object的原型对象为null;
什么是垃圾?
var obj = new Object();
obj = null;
obj指针与堆内存的空间断开了链接:
当一个对象没有任何变量或属性对它进行引用,我们就无法操作它,这个对象就变成了垃圾;他们会占用大量内存空间,影响程序运行;
垃圾回收机制:
自动进行垃圾回收,而我们需要做的就是将不再使用的对象设置为null;
对象分类:内建对象、宿主对象、自定义对象;
我们此前接触的主要是自定义对象;
Function、Object,还有Array(数组)都是内建对象;
var arr = new Array();
typeof arr;//object
arr[0] = 'a';
arr[1] = 'b';
console.log(arr[0]);
console.log(arr[3]);//undefined
// 获取数组长度 length属性
arr.length;
// 如果索引不连续,,使用length会获取到数组的最大索引+1(尽量不要创建非连续的数组)
// length还可以修改(用的不多)
具体JS对象方法可以查阅JavaScript对象参考手册,详细介绍了JS本地对象、内置对象、BOM对象、DOM对象的属性和方法:
方法 | 描述 |
---|---|
concat() | 连接两个或更多的数组,并返回结果。 |
join() | 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。 |
pop() | 删除并返回数组的最后一个元素 |
push() | 向数组的末尾添加一个或更多元素,并返回新的长度。 |
reverse() | 颠倒数组中元素的顺序。 |
shift() | 删除并返回数组的第一个元素 |
slice() | 从某个已有的数组返回选定的元素 |
sort() | 对数组的元素进行排序 (默认按照unicode编码,对数字排序也是,可能会得到不正确的结果;可通过传入回调函数自定义排序规则;) |
splice() | 删除元素,并向数组添加新元素。 |
toSource() | 返回该对象的源代码。 |
toString() | 把数组转换为字符串,并返回结果。 |
toLocaleString() | 把数组转换为本地数组,并返回结果。 |
unshift() | 向数组的开头添加一个或更多元素,并返回新的长度。 |
valueOf() | 返回数组对象的原始值 |
//构造函数方式
var arr = new Array(1,2,3,4,5);
//字面量方式
var arr = [1,2,3,4,5];
// 但二者有区别
var arr = new Array(3);//创建一个长度为3的数组
var arr = [3];//创建一个数组,只有一个数是3
数组中的元素可以是任意数据类型:包括对象、函数等;
数组常用方法:
var arr = [1,2,3,4,5,6,7];
// 最简单常用的for循环
for(var i=0; i<arr.length; i++){
arr[i]
}
// forEach() 支持ie8+,参数是一个回调函数
arr.forEach(function (item,index,array){
item;//数组元素
index;//数组索引
array;//原数组
});
//other
从某个已有的数组返回选中的元素——切片;
arr.slice(start,end);
左闭右开区间;arr.slice(start);
从start开始直到末尾的所有元素;删除元素并向数组添加新元素;
arr.splice(0,2)
从第0个位置开始,删除2个元素,返回值是被删除的元素;arr.splice(0,1,'haha')
第三个位置及以后,可以传递一些新的元素,这些元素会被自动插入到开始索引(这里是0)的前边;小练习:数组去重
例子没有写注释,但解决问题也很有意思,仔细品品;
var arr = [1,2,3,2,2,1,3,4,2,5];
for (var i = 0; i < arr.length ; i++){
for (var j = i + 1; j < arr.length ; j++){
if(arr[i] == arr[j]){
arr.splice(j,1);//这种遍历数组过程中 对数据进行删除 在以前接触的语言中 是不允许的
j--;
}
}
}
对数组的元素进行排序 (默认按照unicode编码,对数字排序也是,可能会得到不正确的结果;可通过传入回调函数自定义排序规则;)
var arr = [2,1,4,3]
arr.sort(function(a,b){
return a - b;//升序
});
arr.sort(function(a,b){
return b - a;//降序
});
函数也是一个对象,函数对象也有相应的对象方法:call() 和 apply()
fun.call()
fun.apply()
区别:
function fun(a,b){
console.log(this);
}
var obj = {
name:'haha'
}
fun.call(obj,'1','2');
fun.apply(obj,['1','2']);
在调用函数时,浏览器每次会传入两个隐含参数:
arguments
;arguments是一个类数组对象:
arguments instanceof Array
或 Array.isArray(arguments)
来进行检验;function fun(){
console.log(arguments.length);//2
console.log(arguments.callee == fun);//true
}
fun("hello","world");
arguments有一个callee属性,它对应一个对象,就是当前正在执行的函数对象;
Date对象也是内建对象的一种,用于表示日期和时间;
var d = new Date();//当前时间
var d1 = new Data("12/30/2020")// 指定日期(是有时区的)
var d1 = new Data("12/30/2020 11:10:30")// 指定时间
d.getDate();//几号
d.getDay();//星期几(0-6,0表示周日)
d.getMonth();//几月(0-11,0表示1月)
d.getFullYear();//哪年
d.getTime();//获取当前对象的时间戳(ms)
Date.now();//获取当前时间戳(利用时间戳可测试代码执行耗时和性能)
Math对象用于执行数学任务。
Math并不是一个构造函数,而是一个工具类;
Math.PI;
Math.abs(1);//计算绝对值
Math.ceil(1.4);//2 (对数进行上舍入)
Math.floor(1.5);//1 (对数进行下舍入)
Math.round(1.5);//2 (对数进行4舍5入)
Math.random();// 0~1之间的随机数(不包括0 和 1)
Math.round(Math.random() * 20);// 0~20之间的随机数(包括0 和 20)
Math.round(Math.random() * 9 + 1);// 1~10之间的随机数(包括1 和 10)
//随机数生成:生成一个x~y之间的随机数
Math.round(Math.random() * (y-x) + x);
Math.max(1,2,3,4,5);//获取多个数中的最值 max/min
Math.pow(x,y);//返回x的y次幂
Math.sqrt(x);//返回数的平方根
基本数据类型:String Number Boolean Null Undefined
引用数据类型:Object
JS提供了三个包装类:
通过包装类可以将基本数据类型的数据转换为对象;
// 使用举例
var num = new Number(3);
console.log(typeof num);//object
var num1 = new Number(3);
num == num1;//false (这里比较的是引用 肯定是false)
平时基本用不到基本数据类型的对象类型,也不会创建它,因为在比较的时候往往会得到不可预料的结果;
方法和属性只能添加到对象中,基本数据类型并没有,但是我们用过的
123.toString()
就是包装类的一种使用场景;浏览器会临时使用包装类将其装换为对象(临时但并未保存装换后的对象结果),然后再调用对象的属性和方法;
基于此,String对应的包装类的方法,我们的基本数据类型字符串就可以直接调用;
var str = "Hello world!"
str.length;//12 -> 获取字符串长度
str[1];//e
str.charAt(1);//e -> 返回指定位置的字符
str.charCodeAt(1);//101 -> 获取指定位置的字符编码(Unicode 十进制)
String.fromCharCode(101);//e -> 根据字符编码获取字符
String.fromCharCode(0x101);//十六进制表示 -> 根据字符编码获取字符
str.concat('haha');//链接两个或多个字符串,作用和+基本一样
str.indexOf('e');//1 -> 检索字符串中是否含有指定内容:
// -> 有的话 返回第一次出现的索引
// -> 没有的话 返回-1
str.indexOf('e',1);//-1 -> 第二个参数 表示从第几个指定字符开始查找
str.lastIndexOf('e');//1 -> 从后往前找,也支持第二个参数
// martch/replace/search:结合正则使用
str.slice(0,2);//He -> 切片字符串,左闭右开区间;两个参数:开始位置 和结束位置索引
str.slice(1);//省略第二个参数 表示从开始到最后
str.slice(1,-1);// 负数 表示从后往前数
str.substring(0,2);// 基本同slice,不同的是:不可以使用负数的参数;而且如果第二个参数小于第一个参数,会自动调整参数位置(交换)
str.substr(3,2);// 开始位置 和 截取长度(非标准定义的方法)
str.split(' ');//将字符串拆分成数组 与数组的join是相反操作
toLowerCase();//大小写装换 不会影响原字符串
toUpperCase();//大小写装换 不会影响原字符串
正则语法参考我的另一篇《正则校验-我需要的正则表达式知识》
正则表达式定义的是一套规则,常用语校验字符串或提取;
JS里正则表达式实际上是一个对象:
// var reg = new RegExp('正则表达式','匹配模式');
var reg = new RegExp('a');//规则:包含a的字符串
var str = 'a';
reg.test(str);//true 严格区分大小写,i模式下 A也能匹配到
// var reg = /正则表达式/匹配模式
var reg = /a/i;
reg.test('a');//true
/[ab]/
包含a或b/[^ab]/
包含除了a 和 b 以外的其他字符/a{3}/
a出现3次/(ab){3}/
ab出现3次/a{1,3}/
a出现1到3次/a{3,}/
a出现3次以上n+
至少一次n*
0或多次n?
0或1次/^a/
以a开头(与在[]
中使用意义完全不同)/a$/
以a结尾/^a$/
完全匹配 只能是一个a/^a|a$/
以a开头 或 以a结尾^$一起使用时,表示完全比配;
使用正则表达式构造函数创建时,对于类似
\.
的转义需要表示为new RegExp("\\.")
,表示其参数是字符串'\.'
;这点与字面量不同;
\.
.是元字符,其他元字符参考文档\\
/\bchild\b/
var str = " a child ";
str = str.replace(/^\s*/g,'')//去开头空格
str = str.replace(/\s*$/g,'')//去结尾空格
str = str.replace(/^\s*|\s*$/g,'')//去开头 和 结尾空格
^1 [3-9] [0-9]{9}$
\w{3,} (\.\w+)* @ [A-z0-9]+ (\.[A-z]{2-5}){1,2}
支持正则表达式的 String 对象的方法:
方法 | 描述 |
---|---|
search | 检索与正则表达式相匹配的值。 |
match | 找到一个或多个正则表达式的匹配。 |
replace | 替换与正则表达式匹配的子串。 |
split | 把字符串分割为字符串数组。 |
var str = "1a2b3c4d5e6f7"
// split:可传递一个正则作为参数,最终会根据正则规则进行拆分
str.split(/[A-z]/);
// 原 search:搜索字符串中是否含有指定内容
str.search('3c');//返回索引(找到时) 或 -1(未找到时)
// search:可接收一个正则参数,根据正则进行检索
str.search(/a[bde]c/);
// match:根据正则提取符合规则的字符串,返回的是一个数组;
str.match(/[A-z]/);//a -> 默认只会找到第一个符合要求的字符
str.match(/[A-z]/g);//[a,b,c,d,e,f] -> 可设置为全局匹配
str.match(/[a-z]/gi);//也可以同时设置多个匹配模式
//replace:不会影响原字符串
str.replace(/[a-z]/gi,'@');//替换掉所有字母