@ TOC近期学习总结
处理兼容性问题的例子
通过这个例子我大概了解了应该怎么样自己去兼容各个版本的浏览器
…
function getScroll() {
//以对象来封装函数 兼容浏览器的滚动条对象 window或者是html或者是body
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
};
}
…
动画函数的封装animat
- 学习了 getComputedStyle(element,null)[attr] 这个获取样式属性值的方法的使用
- 学习了一个思想,样式属性值的封装方法,用一个attr形参代替每一个需要修改的样式属性值
- 动画函数有三个参数,第一个是元素,第二个是对象,第三个是回调函数
animat(element,json,fn),并且对象这个参数里面是以键值对出现,样式属性和样式属性值。
旋转木马案例
- 学习了pop push shift unshift 这四个方法
- pop 删除数组中最后一个元素,返回值是这个被删除的元素
- push 在数组末尾添加一个元素
- shift 删除数组中第一个元素,返回值是这个被删除的元素
- unshift 在数组前面添加一个元素
- 完成了这个旋转木马案例,关键是在JS中以数组的方式存储样式,用一个函数封装好渲染动画,给按钮添加点击事件,每次点击执行完代码后都要调用一次渲染动画
原型的学习
- 学习了原型的第一个好处
-
数据共享,节省内存空间
-
原型中this的指向 :原型和构造函数中的this都是指向构造函数所对应的实例对象
-
JS是一门动态语言,对象没有的属性只要通过 this.属性 就相当于是创建了一个属性,只是没有赋值而言,返回值是undefined
-
原型链以及层层搜索:要调用一个属性或者方法,先在实例对象找,找不到去 --proto-- 所对应的原型对象中找,找不到就报错
-
为内置对象添加方法:在内置对象的原型中添加方法,相当于修改源码 例如以下一个例子:
…//我希望字符串能加一个倒序字符串的方法 String.prototype.myReverse = function () { for (var i = this.length - 1; i >= 0; i--) { console.log(this[i]); } }; var str = "abcdefg"; str.myReverse();
…
- 学习原型的第二个好处:通过改变原型指向实现继承 具体请看下面讲组合继承时一起介绍
四种继承方式
-
改变原型的指向实现继承------有一个缺点:继承来的属性是固定的,修改起来很麻烦
-
借用构造函数实现继承---------有一个缺点:原型中的方法无法继承过来
-
组合继承-----就是改变原型指向和借用构造函数两种继承的结合
…// 组合继承 // 人的构造函数 function Person(name, age) { this.name = name; this.age = age; } // 人的构造函数的原型 Person.prototype.eat = function () { console.log("今天吃了好多东西"); }; // 学生的构造函数 function Student(name, age, score) { this.score = score; //借用构造函数实现继承 Person.call(this, name, age); } //改变原型指向,用于继承方法 Student.prototype = new Person(); Student.prototype.study = function () { console.log("今天学了好多东西,好开心!"); }; var stu = new Student("小华", 16, 100); stu.eat();// ok stu.study();//ok
…
4. 拷贝继承—比较麻烦 较少用:通过for ( var key in 对象.prototype)遍历原型对象来给一个空对象赋值
函数的自调用
格式:(function(){ })(); 或者(function(){ }()); 更加推荐后者
tips:有时候会把构造函数暴露给顶级对象 例如:
… //
(function () {
var num = 10;
//把局部变量给全局变量
//js是一门动态类型的语言,对象没有属性,点了就有了
window.num = num;//window这个对象 只要点了就有这个属性了
)();
console.log(num);//本质上是console.log("window.num")
…
贪吃蛇案例
------感受到了函数封装的操作和好处,体验到了代码的隐秘性和安全性 每个功能都封装成一个个构造函数,通过他们之间的调用联系起来,最终只需要一条代码就可以把所有代码运行起来,这就是面对对象的封装思想和好处
apply call 以及 bind 方法的使用
- apply的使用格式
- 函数名字.apply(对象,[参数1,参数2 …]);
- 方法名字.apply(对象,[参数1,参数2 …]);
- call的使用格式
- 函数名字。call(对象,参数1,参数2, …);
- 方法名字。call(对象,参数1,参数2, …);
区别: 传递参数的方式不同
作用: 改变this的指向
何时用: 只要是想使用别的对象的方法,并且希望这个方法是当前对象的话,就可以考虑用apply或者call方法
- bind的语法:
- 对象.bind(对象,参数…) 返回值是复制之后的这个函数
- 方法.bind(对象,参数…) 返回值是复制之后的这个函数
tips: - 1.这只是复制一份函数,需要另外再调用它
- 2.这个参数可以在复制的时候(也就是bind的括号里)添加,也可以在复制之后的返回值对象中去添加
bind与apply与call的区别:
apply和call是在调用时改变this的指向,bind是在复制的时候改变this的指向的
函数作为返回值和函数作为参数使用
补充知识点: sort()方法是不稳定的,为了使它稳定需要添加一个函数,这个函数作为sort的形参
例如以下例子:
…
//排序,每个文件都有名字,大小,时间,都可以按照某个属性的值进行排序
//三部电影 都有 名字 大小 上映时间
function File(name, size, time) {
this.name = name;//电影名字
this.size = size;//电影大小
this.time = time;//电影上映时间
}
var f1 = new File("jack.avi", "400M", "1997-12-12");
var f2 = new File("tom", "200M", "2017-10-12");
var f3 = new File("xiaosu", "800M", "2010-12-12");
//将实例对象合并为数组
arr = [f1, f2, f3];
//进行排序
//重点 对象的属性用类似数组的形式表示以及函数来封装这种思维要记住 很方便且经常用 obj1.attr == obj1[attr]
创建一个函数fn
function fn(attr) {
//函数作为返回值
return function getSort(obj1, obj2) {
if (obj1[attr] > obj2[attr]) {
return 1;
} else if (obj1[attr] == obj2[attr]) {
return 0;
} else {
return -1;
}
};
}
var ff = fn("size");
//函数作为参数
arr.sort(ff);//重点
//循环输出数组
for (var i = 0; i < arr.length; i++) {
console.log(arr[i].name + "=====>" + arr[i].size + "=====>" + arr[i].time);
}
…
代码有点长,但是是完整的例子,综合的知识点很多,比如函数作为参数,函数作为返回值,对象的属性另外一种方式调用,以及这个案例的思想等等知识点
闭包
这个知识点是顺着函数作为返回值来讲的,所以不太难
原理就是:
- 函数中有一个局部变量,还有一个匿名函数作为返回值,同时这个匿名函数里面会用到刚刚那个局部变量。
- 在之后的运用中只需要接受到这个匿名函数就可以在不重置该变量的前提下操作,也就是数据缓存
闭包分为:函数模式的闭包和对象模式的闭包
特点:数据缓存既是闭包的优点也是缺点 因为缓存会延长变量的生命期,导致无法及时的释放内存
遍历DOM树
它的有一点递归的感觉 :
原理:给一个根节点,输出这个节点的名字以及它的子节点名字,然后判断每一个子节点下面还有没有子节点,如果有就把这个子节点作为一个新的根节点在调用一次,直到没有子节点为止。
这个案例也体现了函数的封装,非常nice,渐渐地在培养面对对象思想
正则表达式
常用的标志:
. 除了 \n 以外的任何一个字符
- 出现0次到多次
- 出现1次到多次
? 出现0次或1次
() 分组 提升优先级
[] 范围 [a-z] [A-Z] [0-9] [0-9a-zA-Z]
{0,} 和*一样
{1,} 和+一样
{0,1} 和?一样
{,9} 不能这样 错误的
| 或者
\d 一个数字
\D 非数字
\s 一个空白符
\S 非空白符
\w 非特殊符号 [0-9a-zA-Z_] 两者是相等的 也就是说 _ 并不是特殊字符
\W 特殊符号
\b 单词边界
^ 以什么开头 取反
$ 以什么结尾
^$ 之间的所有字符代表按照严格模式进行 ^ [a-z][0-9]$ —> b7 t6等都ok bcd7等是不可以的 非严格模式指的是只要是有正则表达式的内容就可以
特殊: g和i
- 正则表达式中 :g 表示的是全局模式匹配
- 正则表达式中 :i 表示的是忽略大小写
正则表达式用处: 重点: 用于表示 比如 邮箱 QQ号码 手机号 地址 编码等一系列的东西,任何语言都适用正则表达式 非常强大