前端学习第十三天——javascript里面的new
用new操作符调用函数
new 函数()
JS规定,使用new
操作符调用函数会进行“四步走”:
- 函数体内会自动创建一个空白对象
- 函数的上下文(this)会指向这个对象
- 函数体内的语句会执行
- 函数会自动返回上下文对象,即使函数没有return语句
构造函数
用new
调用一个函数,这个函数就被成为“构造函数”,任何函数都可以是构造函数,只需要用new
调用它。构造函数用来“构建新对象”,它的内部的语句将为新对象添加若干属性和方法,完成对象的初始化。
构造函数必须用new
关键字调用,否则不能正常工作,开发者约定构造函数命名时首字母要大写
类与实例
JavaScript是“基于对象”(object-based)语言,不同于C++,java等“面向对象”(object-oriented)语言
prototype
任何函数都有prototype
属性,prototype是英语“原型的意思”。prototype
属性值是个对象,它默认用于constructor
属性指回函数
对于普通函数来说prototype
属性没有任何用处,而构造函数的prototype
属性是它的实例的原型。
__proto__
不是W3C标准属性
验证三角关系
<script>
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 实例化
var xiaoming = new People('小明', 12, '男');
// 测试三角关系是否存在
console.log(xiaoming.__proto__ === People.prototype);
// 输出true
</script>
JavaScript规定:实例可以打点访问它的原型的属性和方法,这被称为“原型链的查找”
<script>
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 往原型上添加nationality属性
People.prototype.nationality = '中国';
var xiaoming = new People('小明', 12, '男');
console.log(xiaoming.nationality); // 中国
console.log(xiaoming);
</script>
hasOwnProperty
方法可以检查对象是否真正自己拥有某种方法或某种属性
in
运算符只能检查某个属性或方法是否可以被对象访问,不能检查是否是自己的属性或方法
方法写在prototype
上
每个实例和每个实例的方法函数都是内存中不同的函数,造成了内存的浪费。
解决方法,将方法写在prototype
上
<script>
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 把方法要写到原型上
People.prototype.sayHello = function () {
console.log('你好,我是' + this.name + '我今年' + this.age + '岁了');
}
People.prototype.growup = function () {
this.age ++;
}
var xiaoming = new People('小明', 12, '男');
var xiaohong = new People('小红', 11, '女');
console.log(xiaoming.sayHello === xiaohong.sayHello);
xiaoming.sayHello();
xiaohong.sayHello();
xiaoming.growup();
xiaoming.growup();
xiaoming.growup();
xiaoming.growup();
xiaoming.growup();
xiaoming.sayHello();
xiaohong.sayHello();
</script>
原型链的终点
<script>
function People(name, age) {
this.name = name;
this.age = age;
}
var xiaoming = new People('小明', 12);
console.log(xiaoming.__proto__.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
console.log(Object.prototype.hasOwnProperty('hasOwnProperty')); // true
console.log(Object.prototype.hasOwnProperty('toString')); // true
</script>
关于数组的原型链
<script>
var arr = [344, 45, 34, 23];
console.log(arr.__proto__ === Array.prototype); // true
console.log(arr.__proto__.__proto__ === Object.prototype); // true
console.log(Array.prototype.hasOwnProperty('push')); // true
console.log(Array.prototype.hasOwnProperty('splice')); // true
</script>
继承
子类拥有父类的全部属性和方法,同时子类还应该能定义自己特有的属性和方法
JavaScript特有的原型链特性来实现继承,是普遍的做法。
通过原型链实现继承
<script>
// 父类,人类
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
People.prototype.sayHello = function () {
console.log('你好,我是' + this.name + '我今年' + this.age + '岁了');
};
People.prototype.sleep = function () {
console.log(this.name + '开始睡觉,zzzzz');
};
// 子类,学生类
function Student(name, age, sex, scholl, studentNumber) {
this.name = name;
this.age = age;
this.sex = sex;
this.scholl = scholl;
this.studentNumber = studentNumber;
}
// 关键语句,实现继承
Student.prototype = new People();
Student.prototype.study = function () {
console.log(this.name + '正在学习');
}
Student.prototype.exam = function () {
console.log(this.name + '正在考试,加油!');
}
// 重写、复写(override)父类的sayHello
Student.prototype.sayHello = function () {
console.log('敬礼!我是' + this.name + '我今年' + this.age + '岁了');
}
// 实例化
var hanmeimei = new Student('韩梅梅', 9, '女', '慕课小学', 100556);
hanmeimei.study();
hanmeimei.sayHello();
hanmeimei.sleep();
var laozhang = new People('老张', 66, '男');
laozhang.sayHello();
</script>
面向对象
面向对象的本质:定义不同的类,让类的实例工作
优点:程序编写更清晰、代码结构更严密、是代码更健壮更利于维护
包装类
Numebr()
、String()
、Boolean()
分别是数字、字符串、布尔值的“包装类”。它们的实例都是object类型,它们的PrimitiveValue属性存储它们的本身值
new出来的基本类型值还可以像普通类型值一样参与计算
包装类的目的就是为了让基本类型值可以从它们的构造函数的prototype上获得的方法
// 定义包装类
var a = new Number(123);
var b = new String('前端学习');
var c = new Boolean(true);
console.log(a);
console.log(typeof a); // object
console.log(b);
console.log(typeof b); // object
console.log(c);
console.log(typeof c); // object
console.log(5 + a); // 128
console.log(b.slice(0, 2)); // '前端'
console.log(c && true); // true
var d = 123;
console.log(d.__proto__ == Number.prototype); // true
var e = '前端学习';
console.log(e.__proto__ == String.prototype); // true
console.log(String.prototype.hasOwnProperty('toLowerCase')); // true
console.log(String.prototype.hasOwnProperty('slice')); // true
console.log(String.prototype.hasOwnProperty('substr')); // true
console.log(String.prototype.hasOwnProperty('substring')); // true
Math
Math.round()
可以将一个数字四舍五入为整数
实现四舍五入到小数点的指定位
Math.max()
可以得到参数列表的最大值
Math.min()
可以得到参数列表的最小值
Math.max()
要求参数必须是罗列出来的,而不能是数组
var arr = [3, 6, 9, 2];
var max = Math.max.apply(null,arr);
console.log(max); // 9
apply()
方法可以指定函数的上下文,并且以数组的形式传入“零散值”当做函数的参数
Date
使用new Date()
可得到当前时间的日期对象,object类型值
使用new Date(2021,0,16)
可得到指定日期的日期对象,第二参数表示月份,从0开始计算,0表示1月
也可以写成new Date('2021-01-16')
日期对象的常见方法
方法 | 工能 |
---|---|
getDate() | 得到日期1~31 |
getDay() | 得到星期0~6 |
getMonth() | 得到月份0~11 |
getFullYear() | 得到年份 |
getHours() | 得到小时数0~24 |
getMinutes() | 得到分钟数0~59 |
getSeconds() | 得到秒数0~59 |
时间戳
时间戳表示1970年1月1日零点整距某时刻的毫秒数
通过getTime()
方法或者Date.parse()
函数可以将日期对象变为时间戳。
// 显示时间戳的两种方法。时间戳表示1970年1月1日距离此时的毫秒数
var timestamp1 = d.getTime(); // 精确到毫秒
var timestamp2 = Date.parse(d); // 精确到秒,也是毫秒数,只不过最后三位一定是000
通过new Date(时间错)
的写法,可以将时间戳变为日期对象