1.构造函数和原型
1.1 在ES6之前,是没有类的,是用构造函数来定义的
创建对象可以通过以下三种方式:
-
对象字面量
var obj1 = {};
-
new Object()
var obj2 = new Object();
-
自定义构造函数
function Person(name,age){ this.name = name; this.age = age; } var obj = new Person('zs',12);
1.2 构造函数
构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
在JS中,使用构造函数时要注意以下两点:
- 构造函数用于创建某一类对象,其首字母要大写
- 构造函数要和new一起使用才有意义
new在执行时会做四件事情:
- 在内存中创建一个新的空对象
- 让this指向这个新的对象
- 执行构造函数里面的代码,给这个新对象添加属性和方法
- 返回这个新对象 (所以构造函数里面不需要return)
1.3实例成员和静态成员
function Star(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function() {
console.log('我会唱歌');
}
}
Star.sex = '男';
var ldh = new Star('刘德华', 18);
console.log(ldh.uname);//实例成员只能通过实例化的对象来访问
console.log(Star.sex);//静态成员只能通过构造函数来访问
实例成员:
- 实例成员就是构造函数内部通过this添加的成员,如上列代码中 uname age sing 就是实例
成员 - 实例成员只能通过实例化的对象来访问
静态成员
- 在构造函数本身上添加的成员 如代码中 sex 就是静态成员
- 静态成员只能通过构造函数来访问
- 只要被 static 修饰的属性或者是方法 都属于是静态成员 用的时候 直接用类名.Start.sing()
区别:就是看有没有new对象
1.4 构造函数原型 prototype
构造函数的问题:存在浪费内存的问题。
什么是原型对象?
每一个构造函数,系统都会默认给它设置一个prototype的属性,这个属性的值就是一个object 类型的原型对象。我们可以通过 构造函数 .prototype 来拿到这个原型对象
- 注意:原型对象不叫prototype
- 作用:共享方法
- 原型对象默认是Object类型 Object是所有类的基类
一般情况下,我们的公共属性定义到构造函数里,公共的方法我们放到原型对象
1.5对象原型 __ proto _ _
指向我们构造函数的原型对象
__ proto _ _ 是非标准的
1.6 原型 constructor 构造函数
对象原型( __ proto _ _ )和 构造函数 (prototype)原型对象里面都有一个属性
constructor 属性
- 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动利用 constructor指回原来的构造函数
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
// 很多情况下,我们需要手动的利用constructor 这个属性指回 原来的构造函数
Star.prototype = {
// 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用
constructor指回原来的构造函数
constructor: Star, // 手动设置指回原来的构造函数
sing: function() {
console.log('我会唱歌');
},
movie: function() {
console.log('我会演电影');
}
}
var zxy = new Star('张学友', 19);
console.log(zxy)
1.7 原型链
就是查找属性和方法的规则:
先从自己身上找,如果自己身上有,那么直接用。
如果自己身上没有,找它的原型对象,如果有,就用原型对象的。
如果没有,找原型对象的原型对象 (默认是 Object),如果 Object)的原型对象还没有,找到了最顶null
如果是属性,返回的是undefined 如果是方法,报错
1.8 原型对象中this指向
- 构造函数中的this和原型对象的this,都指向我们new出来的实例对象
1.9 扩展内置对象
本着扩展的原则,原有的方法不去改动,我们只去添加新的方法
Array.prototype.sum = function() {
}
2.继承
继承的特性就是:子承父业,孩子享有父亲的属性和方法
利用组合继承:
- 借调构造函数:利用 call 方法 主要是让属性共享
- 原型继承:把我们子孩子的 prototype = 父亲的实例化对象 new Father 主要是让方法共享
2.1 call()
-
call()可以调用函数
-
call()可以改变这个函数的this指
补充:
js原生中 改变this指向的 三种方法(函数的原型方法)
-
call 方法:改变函数内部this的指向,并且会直接调用这个函数,里面如果要传递参数,传递的是参数的列表 例如: fn.call(obj,1,2)
-
apply 方法:改变函数内部this的指向,并且会直接调用这个函数,里面如果要传递参数,传递的是参数的数组 例如: fn.apply(obj,[1,2])
-
bind 方法:改变函数内部this的指向,不会直接调用这个函数,会返回一个新的函数,如果要传递参数,可以通过bind去传递,也可以调用返回的函数时候传递
var new = fn.bind(obj)
newFn()
-
3. ES5 新增方法
3.1 数组方法
迭代(遍历)方法:forEach()、map()、filter()、some()、every()
- forEach 迭代(遍历)数组
arr.forEach(function(value, index, array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的数组
})
//相当于数组遍历的 for循环 没有返回值
-
filter 过滤数组 (多个)
能够把符合条件的元素放到一个新的数组中
var arr = [12, 66, 4, 88, 3, 7];
var newArr = arr.filter(function(value, index,array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的数组
return value >= 20;
});
console.log(newArr);//[66,88] //返回值是一个新数组
filter方法内部会帮我们遍历这个arr数组,然后每一项根据 return 返回的值 (boolean) 的值,如果是true 就把当前的返回值,如果是false 那么就不返回
-
some 筛选
查找数组中是否满足条件的元素 (一个)
some 查找数组中是否有满足条件的元素 var arr = [10, 30, 4]; var flag = arr.some(function(value,index,array) { //参数一是:数组元素 //参数二是:数组元素的索引 //参数三是:当前的数组 return value < 3; }); console.log(flag);//false返回值是布尔值,只要查找到满足条件的一个元素就立马终止 循环
filter 与 some 区别:
-
filter 也是查找满足条件的元素 返回的是一个数组 而且是把所有满足条件的元素返回回来
-
some 也是查找满足条件的元素是否存在,返回的是一个布尔值,如果查找到一个满足条件的元素就终止循环
-
所以如果查询数组中的唯一元素,用some方法更合适,效率更高
forEach 与 some 区别:
-
在forEach (和 filter ) 里面 return 不会终止迭代
-
在some 里面 return true 会终止迭代
-
return true说明找到了该元素
-
3.2 trim方法去除字符串两端的空格
str.trim()
-
可以解决验证表单时出现的小bug
-
trim() 方法并不影响原字符串本身,他返回的是一个新的字符串
3.3 Object.keys()获取对象的属性名
Object.keys(对象名) 获取到当前对象中所有的属性名 ,返回值是一个数组
3.4 Object.defineProperty设置或修改对象中的属性
只要被Object的defineProperty方法劫持的,都会自动生成一个 set方法和get方法, set方法是获取值得时候调用,get方法是获取值得时候调用
3.5 模糊查找
includes方法判断输入的值是否是需要存在查找的字符串中