一. 构造函数和原型
1.创建对象的三种方式
1、对象字面量
var obj = {};
2、new Object()
var obj = new Object();
3、new构造函数
function Star(){ }
var ldh = new Star();
2.实例成员和静态成员
1、实例成员就是构造函数内部通过this添加
的成员(如下代码中的 name 和 age 是实例成员)
2、静态成员就是在 构造函数本身添加
的成员(如下代码中的 sex 是静态成员)
// 构造函数中的属性和方法我们称为成员,成员可以添加
function Star(name, age){
this.name = name;
this.age = age;
this.sing = function(){
console.log('sing......');
}
}
// 实例成员(name,age)只能通过实例化的对象来访问,不能通过构造函数访问实例成员
var ldh = new Star('刘德华', 20);
console.log(ldh.name); // 刘德华
console.log(Star.name); // undefined
// 静态成员只能通过构造函数来访问,不能通过实例化的对象来访问。
Star.sex = '男';
console.log(Star.sex); // 男
console.log(ldh.sex); // undefined
3.构造函数的问题
构造函数存在浪费内存
的问题,通过new实例会开辟新的内存空间
function Star(name, age){
this.name = name;
this.age = age;
this.sing = function(){
console.log('sing......');
}
}
var ldh = new Star('刘德华', 20);
var zxy= new Star('张学友', 18);
console.log(ldh.sing === zxy.sing); // false 存放的两个不同的内存地址
4.原型对象 prototype
1、原型的概念:是一个对象,通常称prototype为原型对象
。
2、原型的作用:共享方法
总结
:一般情况下,公共的属性定义在构造函数
里,公共的方法定义在原型对象
上。
function Star(name, age){
this.name = name;
this.age = age;
}
Star.prototype.sing = function(){
console.log('sing......');
}
var ldh = new Star('刘德华', 20);
var zxy= new Star('张学友', 18);
console.log(ldh.sing === zxy.sing); // true 原型对象上存放的是同一个内存地址
5.对象原型 __proto__
通常称__proto__为对象原型
。每一个通过new 构造函数
构建出来的实例对象都有一个属性为__proto__
,它指向着构造函数的原型对象即构造函数的.prototype
,所以实例对象可以使用原型对象的属性和方法
。
function Star(name, age){
this.name = name;
this.age = age;
}
Star.prototype.sing = function(){
console.log('sing......');
}
var ldh = new Star('刘德华', 20);
console.log(ldh.__proto__ === Star.prototype); // true
6. 构造函数 constructor
理解:原型对象(prototype)和对象原型(__proto__)
都有一个constructor属性
,它指向着构造函数的本身
(通俗来说,该实例对象是哪个构造函数构建出来的?)。
作用:1.记录xx实例对象是xx构造函数的引用
2.原型对象利用constructor属性指向构造函数
。
function Star(name, age) {
this.name = name;
this.age = age;
}
/*如果在构造函数原型对象要共享的方法比较多,一般采用对象形式书写.
所以则会把新的对象覆盖掉Star的原型对象,需要手动指回原来的构造函数*/
Star.prototype = {
constructor: Star,
sing: function() {
console.log('sing......');
},
dance: function() {
console.log('dance......');
}
}
var ldh = new Star('刘德华', 20);
console.log(Star.prototype.constructor); // Star
console.log(ldh.__proto__.constructor); // Star
二. 继承
ES5 继承
<script>
//es5继承
//我们创建一个父函数person 让student函数来继承person
//创建 Person
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.hello = function () {
console.log('hello 继承');
}
//创建 Student 让他继承 Person
function Student(name, age, sid) {
//下面是继承属性的过程
//首先 name和age属性我希望可以通过Person继承得到
//我们可以通过函数的调用来实现Person的复用
// Person(name,age)
//但上面的写法,在Person中的this 就会指向 window 而window是没有这两个属性的
//所以我们可以强行改变Person函数中this的指向 可以通过 call apply bind方法中的随意一个
//这里我们用call call的用法为 call(要this指向的对象,参数1,参数2);
Person.call(this, name, age); //这里在this为 Student
this.sid = sid;
}
//下面是继承方法的过程
//首先我们知道Person的方法是存放在prototype上面的 那么我们要做的就是,将Student的prototype 指向Person的prototype就可以了
// Student.prototype=Person.prototype;
//但这种方式会出现一个问题,就是在给Student添加方法的话,就会直接添加到Person上
//所以我们可以创建一个空元素,让他的__proto__指向Person的prototype
let tmp = Object.create(Person.prototype);
// Object.create(对象A) 返回一个空对象 其__proto__指向对象A的prototype
//然后将 Student的prototype 指向空对象的__proto__
Student.prototype = tmp;
//如果子类的方法与父类方法同名,想要执行父类的方法,子类的方法要在继承之后写
Student.prototype.hello = function () {
console.log('hello 继承!!!')
}
let p = new Person('xiaoxiao', 6);
console.log(p.name, '-', p.age);
p.hello();
let s = new Student('xiaoming', 18, '1653');
console.log(s.name, '-', s.sid);
s.hello();
</script>
ES6 继承
<script>
//es6的继承是通过extends实现的
//同样我们创建一个父函数Person,让Student来继承
//创建Person
class Person {
constructor(name, age) {
this.age = age;
this.name = name;
}
hello() {
console.log('hello world')
}
}
//创建 Student
class Student extends Person {
constructor(name, age, sid) {
//es6的属性与方法继承,通过super
super(name, age);
this.sid = sid;
}
//如果想执行student自己的hello方法
hello() {
console.log('hello node.js')
}
}
let p = new Person('xiaoxiao', 6);
console.log(p.name, '-', p.age);
p.hello();
let s = new Student('xiaoming', 18, '1653');
console.log(s.name, '-', s.sid);
s.hello();
</script>
三. 常用方法
1. 数组方法
- foreach()
循环遍历数组,没有返回值
参数:value为数组中的每一项,index为每一项的索引值,arr则为数组的本身, 。
var arr = [1,2,3,4];
arr.foreach((item,index,arr) => {
console.log('当前项:', item); // 1,2,3,4
console.log('当前项索引值:', index); // 0,1,2,3
console.log('数组:', arr); // 输出4次 [1,2,3,4]
})
- map()
创建一个的新数组并返回,不影响原数组
。:
var arr = [1, 2, 3, 4];
var newArr = arr.map((item, index) => item % 2 === 0));
console.log(newArr); // [2,4]
- filter()
一般用于数组过滤,符合条件的元素组成新的数组并返回,没有符合条件则返回空数组。不影响原数组。
var arr = [10, 20, 30, 40];
var newArr = arr.filter((item, index, arr) => item > 20);
console.log(newArr); // [30, 40]
- some() 用于查找数组中符合条件的元素,如果
任意一项符合条件则返回,会终止循环,不再继续往下执行,一项符合条件返回true, 否则返回false
*注意:空数组返回false
var arr = [10, 20, 30, 40, 50];
var flag = arr.some((item, index) => item > 100);
console.log(flag); // false
console.log([].some(item => item)); // false
- every()
用于查找数组中符合条件的元素,如果每一项都符合条件则返回true, 否则返回false
*注意:空数组返回true
var arr = [10, 20, 30, 40, 50];
var flag = arr.every((item, index) => item > 5);
console.log(flag); // true
console.log([].every(item => item)); // true
2. 字符串方法
- trim()
用于去除字符串首尾空格,并返回去掉空格后的字符串。
var str= ' abc ';
var newStr = str.trim();
console.log(newStr); // abc
3.对象方法
- Object.keys()
用于获取对象自身所有的属性(类似于for...in)并返回由属性名组成的数组
var obj = {
name: 'tao',
age: 18
}
var arr = Object.keys(obj);
console.log(arr); // ['name', 'age']
- Object.defineProperty()
用于定义新属性或修改原有的属性
Object.defineProperty(obj, prop, descriptor)
obj 需要定义属性的当前对象
prop 当前需要定义的属性
descriptor 属性描述符。
var obj = {};
// 用defineProperty定义和修改属性
Object.defineProperty(obj, 'name', {
value: 'tao',
enumerable: false, // 是否可遍历 默认false
writable: false, // 是否可重写 默认false
configureable: false // configurable属性性表示对象的属性是否可以被删除,以及除writable属性外的其他属性是否可以被修改。
})
console.log(obj);