1.面向过程与面向对象
2.对象与类
this.uname = name;
3.构造函数和原型
3.1 静态成员和实例成员
实例成员 :实例成员就是构造函数内部通过this添加的成员,实例成员只能通过实例化的对象来访问
以下代码里的 uname age sing就是实例成员
function Star(uname, age) { this.uname = uname; this.age = age; this.sing = function() { console.log('我会唱歌'); } } var ldh = new Star('刘德华', 18); console.log(ldh.uname); //实例成员只能通过实例化的对象来访问
静态成员 :在构造函数本身上添加的成员 静态成员只能通过构造函数来访问 在ES5中只要被static修饰的属性和方法都是静态成员
下列代码中 sex 就是静态成员
function Star(uname, age) { this.uname = uname; this.age = age; this.sing = function() { console.log('我会唱歌'); } } Star.sex = '男'; var ldh = new Star('刘德华', 18); console.log(Star.sex); //静态成员只能通过构造函数来访问
3.2构造函数的问题
存在浪费内存的问题
function Star(uname , age) { this.uname = uname; this.age = age; this.sing = function(){ console.log('我会唱歌') } } var ldh = new Star("刘德华",18); var shuji= new Star("书记",22); ldh.sing(); shuji.sing();
以上代码在调用sing方法时都会在内存开辟一个新的空间,如果有多个对象来调用sing方法就会占用过多内存,所以我们就用到了构造函数的原型 prototype。
3.3 构造函数原型prototype
构造函数通过原型分配的函数是所有对象所共享的。
JavaScript 规定,每一个构造函数都有一个prototype 属性,指向另一个对象。注意这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。
构造函数.prototype就可以获取原型对象
function Star(uname, age) { this.uname = uname; this.age = age; } Star.prototype.sing = function() { console.log('我会唱歌'); } var ldh = new Star('刘德华', 18); var zxy = new Star('张学友', 19); ldh.sing(); //我会唱歌 zxy.sing(); //我会唱歌
3.4 对象原型
实例化对象都会有一个__proto__属性指向构造函数的原型对象,而我们的实例化对象可以使用对象原型的属性和方法就是因为有__proto__属性的存在
实例化对象.__proto__ === 构造函数.prototype
它们的三角关系如下图:
__proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype
3.5 constructor构造函数
对象原型( __proto__)和构造函数(prototype)原型对象里面都有一个属性constructor 属性
constructor 我们称为构造函数,因为它指回构造函数本身。
constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。
3.6 原型链和查找机制
每一个实例对象又有一个proto属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有proto属性,这样一层一层往上找就形成了原型链。
查找机制:
当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性,如果自身有,就有自身的属性和方法。
如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。
如果还没有就查找原型对象的原型(Object的原型对象)。依此类推一直找到 Object 为止(null)。
如果找到尽头(null)都没找到,是属性则返回undefined,是方法则报错
3.7 原型对象中this的指向
构造函数中的this和原型对象的this,都指向我们new出来的实例对象
3.8 通过原型对象为数组扩展内置方法
var arr = [3,6,9,8,5] arr.prototype.sum = function() { var sum = 0; for (var i = 0; i < this.length; i++) { sum += this[i]; } return sum; }; //此时数组对象中已经存在sum()方法了 可以用于数组.sum()进行数据的求和
4.继承
4.1 call()
call()可以调用函数 可以修改this的指向,使用call()的时候,()里的第一个参数是修改的this指向,参数2 参数3 使用逗号隔开
function fn(x, y) { console.log(this); console.log(x + y); } var o = { name: 'andy' }; fn.call(o, 1, 2); //调用了函数此时的this指向了对象o,
4.2 构造函数继承属性
// 1. 父构造函数 function Father(uname, age) { // this 指向父构造函数的对象实例 this.uname = uname; this.age = age; } // 2 .子构造函数 function Son(uname, age, score) { // this 指向子构造函数的对象实例 //3.使用call方式实现子继承父的属性 Father.call(this, uname, age); this.score = score; } var son = new Son('刘德华', 18, 100); console.log(son);
4.3 借用原型对象继承方法
// 1. 父构造函数 function Father(uname, age) { // this 指向父构造函数的对象实例 this.uname = uname; this.age = age; } Father.prototype.money = function() { console.log(100000); };
// Son.prototype = Father.prototype; 这样直接赋值会有问题,如果修改了子原型对 象,父原型对象也会跟着一起变化 Son.prototype = new Father(); // 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数 Son.prototype.constructor = Son; // 这个是子构造函数专门的方法 Son.prototype.exam = function() { console.log('孩子要考试'); } var son = new Son('刘德华', 18, 100); console.log(son);
5.ES5新增方法
5.1 forEach()遍历数组 没有返回值
array.forEach(function(value , index , array){....})
value是每个数组元素
index是每个元素索引值
array是当前数组
5.2 filter()筛选数组 其实也会遍历数组
array.filter(function(value , index , array){
return 条件表达式
})
返回的是一个新数组 括号跟的参数都是一样的
5.3 some() 查找数组中是否有满足条件的元素 其实也会遍历数组
array.some(function(value , index , array){
return 条件表达式
})
返回值是布尔值,只要查找到第一个满足条件的元素就会终止循环 效率高
5.4 trim方法去除字符串两端的空格
字符串的特性 不可变性
var str = ' hello ' ; console.log(str.trim()) //hello 去除两端空格 var str1 = ' he l l o ' ; console.log(str1.trim()) //he l l o 去除两端空格
5.5 获取对象的属性名
Object.keys(对象) 获取到当前对象中的属性名 ,返回值是一个数组
var obj = { id: 1, pname: '小米', price: 1999, num: 2000 }; var result = Object.keys(obj); console.log(result) //返回的新数组[id,pname,price,num]
5.6 Object.defineProperty设置或修改对象中的属性
Object.defineProperty(对象,修改或新增的属性名,{ value:修改或新增的属性的值, writable:true/false, //如果值为false 不允许修改这个属性值 enumerable: false, //enumerable 如果值为false 则不允许遍历 configurable: false //configurable 如果为false 则不允许删除这个属性 属性是否可以被删除或是否可以再次修改特性 })