一. 继承的几种方式
1.继承
// 封装一个对象之间继承的函数
function extend(parent, child) {
for (var k in parent) {
// 子级有的属性不需要继承
if (child[k]) {
continue;
}
child[k] = parent[k];
}
}
对象拷贝:for……in :父对象的属性拷贝给子对象。
2.原型继承
// 封装的构造函数就是用来创建一类对象
// 继承指的是 类型 和 类型之间的继承
// 人类类型
function Person(name,age,sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 学生类型
function Student(score) {
this.score = score;
}
// 老师类型
function Teacher(salary) {
this.salary = salary;
}
// 原型对象,可以将自己的属性和方法继承给将来的实例对象使用
Student.prototype = new Person("zs",18,"男");
Student.prototype.constructor = Student;
// 生成一个实例
var s1 = new Student(89);
var s2 = new Student(100);
console.log(s1.name);
console.log(s1.constructor);
3.构造函数的继承
- 认识call方法
// call
// 函数本身就是一种对象,就能够有自己的属性和方法
// call 方法本身是一种执行函数的方法
function fn(a,b) {
console.log(this);
console.log(a + b);
}
var o = {
name: "zs"
}
// 普通函数调用
// fn(2,3);
// call 方法在调用函数的时候,有两个功能
// 1.更改函数内部的 this 指向
// 2.调用函数执行内部代码
// 参数: 第一个参数用来指定 this,第二个及以后,就是传的实参
fn.call(o,3,4);
- 构造函数属性的继承(举例)
// 人类类型
function Person(name,age,sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 学生类型
function Student(name,age,sex,score) {
// 直接对父类型的构造函数进行一个普通调用
// Person 普通调用过程中,内部的 this 指向的是 window
// 可以通过 call 方法更改Person 内部的 this
Person.call(this,name,age,sex);
this.score = score;
}
// 老师类型
function Teacher(name,age,sex,salary) {
Person.call(this,name,age,sex);
this.salary = salary;
}
// 创建学生的实例对象
var s1 = new Student("zs",18,"男",89);
var s2 = new Student("ls",19,"男",92);
- 构造函数的原型方法继承(举例)
// 人类类型
function Person(name,age,sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 父类型的原型对象中有方法也需要继承
Person.prototype.sayHi = function () {
console.log("你好");
};
// 学生类型
function Student(name,age,sex,score) {
Person.call(this,name,age,sex);
this.score = score;
}
// 子类型的原型对象上,需要继承父类型原型对象的方法
// 方法1:对象拷贝继承
for (var k in Person.prototype) {
// 保留自己的 constructor 不要进行继承
if (k === "constructor") {
continue;
}
Student.prototype[k] = Person.prototype[k];
}
// 方法2:原型继承
Student.prototype = new Person();
Student.prototype.constructor = Student;
// 老师类型
function Teacher(name,age,sex,salary) {
Person.call(this,name,age,sex);
this.salary = salary;
}
// 创建学生的实例对象
var s1 = new Student("zs",18,"男",89);
s1.sayHi();
4.组合继承
- 函数属性在构造函数内部继承,方法通过原型继承
function Person(name,age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHi = function () {
console.log("你好");
}
// 生成一个子类型
function Teacher(name,age,salary) {
// 继承父类的属性
Person.call(this,name,age);
this.salary = salary;
}
// 方法继承,通过原型对象继承
Teacher.prototype = new Person();
Teacher.prototype.constructor = Teacher;
// 生成老师的一个实例
var t1 = new Teacher("wang",45,10000);
console.dir(t1);
console.log(t1.name);
t1.sayHi();
二.函数定义方式
- 函数声明
1.声明时必须定义函数名
function fun() {
console.log(1);
}
- 函数表达式
1.将函数赋值给一个变量,可以是一个匿名函数 - new Function
1.通过构造函数方法定义函数
2.函数本身也是一种对象
var fun = new Function('a','b','var a = "1";console.log(a+b)');
fun(2,3);
函数声明与函数表达式的区别
• 函数声明必须有名字
• 函数声明会函数提升,在预解析阶段就已创建,声明前后都可以调用
• 函数表达式类似于变量赋值
• 函数表达式可以没有名字,例如匿名函数
• 函数表达式没有函数提升,在执行阶段创建,必须在表达式执行之后才可以调用
三.函数的调用
- 普通的函数,是通过 给函数名或者变量名添加 () 方式执行,
- 内部的 this 默认指向 window
2.构造函数,是通过 new 关键字进行调用
- 内部的 this 指向的是将来创建的实例对象
function Person(name) {
this.name = name;
console.log(this);
}
var p1 = new Person("zs");
Person();
3.对象中的方法,是通过对象打点调用函数,然后加小括号
- 内部的 this 默认指向的是调用的对象自己
var o = {
sayHi: function () {
console.log("haha");
},
}
o.sayHi();
this 的指向是要联系执行的上下文,在调用的时候,是按照什么方式调用,指向是不一样的
4.事件函数,不需要加特殊的符号,只要事件被触发,会自动执行函数
- 事件函数的内部 this 指向的是事件源
5.定时器和延时器中的函数,不需要加特殊的符号,只要执行后,在规定的时间自动执行
- 默认内部的 this 指向的是 window
setInterval(function () {
console.log("time");
},1000);