// 使用构造函数创建对象
function People(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.say = function() {
console.log('hello');
}
}
var a = new People('小明', 13, '男');
console.log(a);
// 字面量
var obj = {
name: '小敏',
age: 12
};
// new Object()
var obj2 = new Object();
obj2.name = '小红';
obj2['age'] = 12;
console.log(obj2);
function People(uname, age, sex) {
this.uname = uname;
this.age = age;
this.sex = sex;
this.say = function() {
console.log('hello');
}
}
var a = new People('小明', 13, '男');
// 1. 实例成员: 只能通过实例对象才能访问的属性或方法
console.log(a.uname);
console.log(People.uname); //undefined ,原因是uname不在People内
// 2. 静态成员:给构造函数添加的属性或方法, 只能通过构造函数本身才能访问的属性或方法
People.height = 'height';
console.log(a.height); //undefined ,原因是height不在a内
console.log(People.height);
构造函数中直接添加方法的缺点
每次创建对象,要重复开辟内存空间,浪费资源
构造函数的原型 prototype
每个函数默认都有一个 propotype 属性, 它的值默认是一个对象
在 prototype 对象上的方法和属性, 会被 new 构造函数() 创建出来的实例对象所继承
注意:
(1) 只要是函数就默认有 prototype 属性, 但非函数的对象是不具有的
(2) 定义构造函数时, 公共的方法定义在原型对象上, 这样可以被所有创建出来的实例直接继承
function Student(uname, age) {
this.uname = name;
this.age = age;
}
// 每个函数默认都有一个 propotype 属性, 它的值默认是一个对象
Student.prototype.sing = function() {
console.log('哈哈哈哈');
}
Student.prototype.study = '学习JS';
var xm = new Student('小明', 15);
// 在prototype上添加的方法或属性会被所有的实例对象继承
console.log(xm.study);
xm.sing();
var obj = {
a: 1
};
// console.log(obj.prototype); //非函数没有此属性
对象的原型
每个对象都默认有一个 __proto__的属性, 它的值是一个对象, 默认指向创建这个对象的构造函数的原型
对象原型的访问特点
每个对象访问__proto__下的所有属性和方法,可以省略__proto__
对象上读取属性的顺序
先从自身的属性上进行查找,如果没有再去__proto__属性指向的对象上去查找
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O6w9IGIo-1614155392507)(E:\黑马培训\前端基础\案例练习\就业班\笔记\JS高级\JS高级第二天\images\img4.png)]
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)
每一个实例对象又有一个__proto__属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找就形成了原型链。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4q8gDGJ-1614155392508)(E:\黑马培训\前端基础\案例练习\就业班\笔记\JS高级\JS高级第二天\images\img5.png)]
每个实例对象( object )都有一个私有属性(称之为 proto )指向创建它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( proto ) ,层层向上直到一个对象的原型对象为 null。
对象访问属性时遵从原型链的顺序
(1) 当访问一个对象的属性时,首先从这个对象自身进行查找
(2) 如果没有找到就从它的原型对象(proto)中查找
(3) 如果还没有找到,继续沿着对象的原型链层层向上查找,直到最末尾的 null
构造函数中的this和原型对象的this,都指向我们new出来的实例对象
// 非函数中this指向window
// 函数中this指向函数调用者
var that;
function Student(uname, age) {
// 函数中的 this 默认指向函数的调用者
this.uname = name;
this.age = age;
}
// 每个函数默认都有一个 propotype 属性, 它的值默认是一个对象
Student.prototype.sing = function() {
that = this;
console.log('哈哈哈哈');
}
Student.prototype.sleep = function() {
console.log(this === Student.prototype);
console.log('去睡觉');
}
var xm = new Student('小明', 15);
xm.sing();
console.log(that === xm);
// sing 中this指向调用者Student.prototype
Student.prototype.sleep();
var arr = [1, 2, 3]
console.log(arr.__proto__ === Array.prototype);
arr.push(4);
// 1. 需求:修改数组 Array 上的原型对象,添加自定义求和的方法
Array.prototype.getSum = function() {
console.log(this); //指向arr=[1,2,3,4]
var sum = 0;
for (var i = 0; i < this.length; i++) {
sum += this[i];
}
return sum;
}
console.log(arr.getSum());
拓展原型对象上的方法时,不能直接覆盖原来的原型对象,只能添加或和修改方法 注意:内置对象(如:Object, Array, Function) 上的原型对象不允许进行覆盖,只允许修改
// 子类继承父类属性的核心: 使用 call() 把父类的实例对象 this 手动修改为子类的实例对象 this
function People(name, age) {
console.log(this); //this指向父类创建的实例对象
this.name = name;
this.age = age;
}
function Student(name, age) {
// this指向子类创建的实例对象
People.call(this, name, age);
}
var xm = new Student('小明', 15);
console.log(xm);
// 子类继承父类上方法的核心: 新建一个对象作为子类的原型对象, 并把这个对象的原型指向父类的 prototype
function People(name, age) {
console.log(this); //this指向父类创建的实例对象
this.name = name;
this.age = age;
};
People.prototype.say = function() {
console.log('hello');
};
function Student(name, age, subject) {
// this指向子类创建的实例对象
People.call(this, name, age);
this.subject = subject;
};
// 三种方法可以调用父类方法:
// (1)直接把父构造函数的原型拿过来用,但是会导致子类添加的方法,父类也会有
Student.prototype = People.prototype;
// 2) 不能把两个原型放在一个空间, 需要创建一个新的内存空间
var obj = {
constructor: Student, //把constructor指向子构造函数
__proto__: People.prototype, //通过原型链,把父构造函数的原型直接拿过来;
}
Student.prototype = obj;
// (3)实例化父级的构造函数
Student.prototype = new People();
Student.prototype.constructor = Student;
// 子类构造函数原型上添加新的方法
Student.prototype.sleep = function() {
console.log('去睡觉啊');
}
var xm = new Student('小明', 15, '语文');
xm.say(); //xm直接访问父构造函数原型上的方法;
console.log(xm);
console.log(People.prototype); //检测父构造函数上的原型是否被子构造函数修改
console.log(xm.constructor); //检测xm是谁创建出来的
var arr = [10, 12, 55, 13]
arr.forEach(function(item, index, arr) {
console.log('索引号:' + index + '===>' + '数组元素:' + item);
})
var arr2 = [1, 2, 3, 4, 5, 6];
var newArr = arr2.filter(function(item,index) {
// 如果return后面的结果为真,就返回到新数组中
return item % 2 == 0;
})
console.log(newArr);
var arr = ['hello', '12', ' ', 'true', '']
var a = arr.some(function(item, index){
return item == '';
})
console.log(a);
var arr3 = [30, 22, 45, 16, 20];
var b = arr3.every(function(item, index) {
return item > 20;
})
console.log(b);
// 这些方法本质上都是存在原型上 Array.prototype;
console.log(arr3.__proto__ === Array.prototype); //true
var str = ' hello '
console.log(str.trim()) //hello 去除两端空格
var str1 = ' he l l o '
console.log(str.trim()) //he l l o 去除两端空格
Object.keys(对象) 获取到当前对象中的属性名
var obj = {
a: 1,
b: 2,
c: 3
};
for (var key in obj) {
console.log(obj[key]);
}
// 1. 使用 Object.keys() 方法获取对象上所有的属性名
// 返回值:所有属性名组成的数组
var res = Object.keys(obj);
console.log(res);
// 2. 新遍历对象的方法
res.forEach(function(item) {
console.log(item); //获取的是属性名
console.log(obj[item]); //获取属姓名对应的值,注意都是变量,要用[]
})
作用:在对象上定义一个新属性,或者修改原属性,并返回对象
使用方法:
Object.defineProperty(obj, prop, descriptor)
(1) obj: 要定义属性的对象
(2) prop: 要定义或修改的属性的名称, 字符串 ‘name’
(3) descriptor: 要定义或修改的属性描述符, 数据格式是对象 {}
属性的描述符:
(1) value: 属性值
(2) writable: 是否可以修改
(3) enumerable: 是否可以枚举(遍历到)
(4) configurable: 是否可以删除或再次修改特性
三个属性描述符默认都是 false
var obj = {
name: '张三',
age: '12',
gender: 'man'
}
Object.defineProperty(obj, 'height', {
value: '170',
writable: true, //属性可以修改
enumerable: true, //可以遍历到
configurable: true //可以再次修改
})
obj.height = '175';
console.log(Object.keys(obj));
// 删除属性 delete;
delete obj.height;
console.log(obj.height);