创建对象的方法
// 使用new Object创建对象
let obj = new Object();
// 使用对象字面量创建对象
let obj2 = {};
// 使用构造函数创建对象
function Star(username, age) {
this.username = username;
this.age = age;
this.sing = function() {
console.log("song");
};
}
let p = new Star("jack", 19);
p.sing();
实例成员和静态成员
// 使用构造函数创建对象
function Star(username, age) {
// 构造函数内部通过this添加的成员,称为实例成员,只能通过实例化的对象来访问
this.username = username;
this.age = age;
this.sing = function() {
console.log("song");
};
}
let p = new Star("jack", 19);
p.sing();
// 在构造函数本身添加的成员就是静态成员
Star.sex = "男";
// 只能通过构造函数来访问,不能通过对象来访问
console.log(Star.sex);
构造函数存在浪费内存的问题
构造函数通过原型分配的函数式所有对象共享的,这个对象的所有属性和方法,都会被构造函数所拥有。
把不变的方法直接定义在prototype对象上,所有的对象的实例就可以共享这些方法
function Star(username, age) {
// 公共属性定义到构造函数里
this.username = username;
this.age = age;
}
// 公共方法放到原型对象上
// Star.prototype.sing = function() {
// console.log("song");
// };
// Star.prototype.movie = function() {
// console.log("movie");
// };
Star.prototype = {
// 如果修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动指向原来的构造函数
constructor: Star,
sing: function() {
console.log("song");
},
movie: function() {
console.log("movie");
}
};
// 对象都会有一个__proto__指向构造函数的prototype原型对象,
// 对象之所以能够使用构造函数的prototype原型对象的方法,就是因为有__proto__原型的存在。
// 虽然没有定义p对象的方法,但是系统自动为p对象身上添加__proto__指向构造函数的原型对象。
let p = new Star("jack", 19);
// 方法查找规则:首先查找p对象有没有sing方法,有就执行sing方法,没有就去构造函数原型上查找sing方法
p.sing();
// console.dir(Star);
// console.log(p.__proto__ === Star.prototype);
console.log(Star.prototype.constructor);
console.log(p.__proto__.constructor);
console.log(Star.prototype);
console.log(p.__proto__);
原型链
function Star(username, age) {
this.username = username;
this.age = age;
}
Star.prototype.sing = function() {
console.log("song");
};
let p = new Star("jack", 19);
// 只要是对象就有有__proto__原型,指向原型对象
console.log(Star.prototype);
// 在Star原型对象里面的__proto__原型指向的是Object.prototype
console.log(Star.prototype.__proto__ === Object.prototype);
// Object.prototype原型对象里的__proto__原型指向为null
console.log(Object.prototype.__proto__);
对象成员查找规则
function Star(username, age) {
this.username = username;
this.age = age;
}
Star.prototype.sing = function() {
console.log("song");
};
// Star.prototype.sex = "man";
Object.prototype.sex = "woman";
let p = new Star("jack", 19);
p.sex = "man";
// 访问对象的属性和方法时,(就近原则)先查找对象自身有没有该属性,没有就找prototype原型对象上的,再没有就找Object的原型对象
console.log(p.sex);
原型对象this指向
// 在构造函数中,里面的this指向的是实例对象p
function Star(username, age) {
this.username = username;
this.age = age;
}
let that;
Star.prototype.sing = function() {
console.log("song");
that = this;
};
let p = new Star("jack", 19);
p.sing();
// 原型对象函数里的this指向的是实例对象p
console.log(that === p); // true
利用原型对象扩展内置对象方法
Array.prototype.sum = function() {
let sum = 0;
for (let i = 0; i < this.length; i++) {
sum += this[i];
}
return sum;
};
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(arr.sum());
console.log(Array.prototype);
call 调用这个函数,并修改函数运行时的this指向
function fn(x, y) {
console.log("hello");
// 指向window
// console.log(this);
console.log(x + y);
}
let o = {
name: "andy"
};
// 1. call()可以调用函数
// fn.call();
// 2. 改变这个函数的this指向,在函数里面指向了o这个对象,并传递了参数
fn.call(o, 1, 2);
借用父构造函数来继承属性和方法
// 借用父构造函数来继承属性
function Father(username, age) {
// 里面的this指向的是父构造函数的对象实例
this.username = username;
this.age = age;
}
Father.prototype.money = function() {
console.log("money");
};
function Son(username, age, score) {
// 里面的this指向的是子构造函数的对象实例,使用call之后,父构造函数里面的this变成了子函数里的this
Father.call(this, username, age);
this.score = score;
}
// 继承Father的方法,但不会影响Father类
Son.prototype = new Father();
// 如果利用对象的形式修改了原型对象,别忘了利用constructor指回原来的构造函数
Son.prototype.constructor = Son;
// 子构造函数的独有方法,不会改变影响父类
Son.prototype.exam = function() {
console.log("exam");
};
let p = new Son("jack", 19, 100);
p.money();
p.exam();
console.log(p);
console.log(Father.prototype);
console.log(Son.prototype.constructor);
类的本质
其实还是一个function
class Star {}
console.log(typeof Star); // function
Foreach
let arr = [1, 2, 3];
let sum = 0;
arr.forEach((value, index, array) => {
// console.log("每个数组元素", value);
// console.log("每个数组元素的索引号", index);
// console.log("数组本身", array);
sum += value;
});
console.log(sum);
filter
let arr = [32, 18, 78, 40, 11, 13];
// filter遍历,通过筛选返回一个新的数组
let temp = arr.filter((value, index) => {
// return value >= 20;
return value % 2 === 0;
});
console.log(temp);
some
let arr = [32, 18, 78, 40, 11, 13];
// some 查找数组中是否有满足条件的元素(数组当前项的值,索引,数组本身),
// 返回一个布尔值,如果找到就返回为true,找到第一个满足的就终止循环
let flag = arr.some((currentValue, index, arr) => {
// return currentValue % 2 === 0;
return currentValue > 100;
});
console.log(flag);
filter some区别
filter查找满足的元素,返回一个数组,把所有满足的元素返回来
trim
let str = " 2 2 4 ";
console.log(str.trim());
console.log(str.trimstart());
console.log(str.trimLeft());
Object.defineProperty
let obj = {
id: 1,
name: "jack",
age: 19
};
/**
* obj 目标对象 prop 需定义或修改属性的名字 descriptor 目标属性所拥有的特性
* Object.defineProperty(obj, prop, descriptor);
* **/
// 修改存在的属性
Object.defineProperty(obj, "age", {
value: 20
});
// 是否允许修改属性值,默认为false
Object.defineProperty(obj, "id", {
writable: true
});
obj.id = 2;
// 没有就是新增属性,定义一个num的属性,值为1000
Object.defineProperty(obj, "num", {
value: 1000,
// 是否可以重写,默认为false
writable: false,
// enumerable为false,则不会被枚举,默认值是false
enumerable: false,
// configurable 目标属性是否可以删除或再次修改,默认为false
configurable: false
});
console.log(obj); // {id: 2, name: "jack", age: 20, num: 1000}
console.log(Object.keys(obj)); // ["id", "name", "age"]
delete obj.num;
console.log(obj); // num 不可被删除
// 上面设置了num不可被再次定义,所以再次修改就不可以了
Object.defineProperty(obj, "num", {
value: 1000,
writable: true,
enumerable: true,
configurable: true
});
Object.keys()
let obj = {
id: 1,
name: "jack",
age: 19
};
/**
* Object.keys()获取对象自身所有的属性
* 类似于for..in
* 返回一个由属性名组成的数组
* **/
let arr = Object.keys(obj);
// 遍历属性名
arr.forEach(value => {
console.log(value);
});
ronle 发布了2 篇原创文章 · 获赞 0 · 访问量 81 私信 关注