学习JavaScript进阶记录(二)
目录
一、对象
1、创建对象的三种方式
1.1利用字面量创建对象
1.2通过new Object创建对象
1.3利用构造函数创建对象
2、实例成员和静态成员
3、内置构造函数
Object
Array
String
Number
二、原型
1、介绍
2、constructor
3、对象原型
4、原型继承
5、原型链
一、对象
1、创建对象的三种方式
1.1利用字面量创建对象
const obj1 = {name: 'niko',
}
1.2通过new Object创建对象
const obj2 = new Object({name: 'niko',
})
1.3利用构造函数创建对象
js的构造函数在语法上是常规函数。一般约定两个规则:函数命名以大写字母开头。由 new 操作符执行。
function Person(Name, age, gender) {this.Name = Name;this.age = age;this.gender = gender;
}
const niko = new Person("Niko", 20, "Male");
- new 调用函数的行为被称为实例化。
- 实例化构造函数时,没有参数可以省略括号。(不推荐)
- 构造函数内部不用写 return,返回值就是创建的对象。
实例化过程:
- new 创建一个空对象。
- 构造函数的 this 指向这个对象。
- 执行构造函数的代码,给空对象添加属性。
- 返回这个对象。
2、实例成员和静态成员
实例成员:构造函数创建的对象叫实例对象,实例对象里的方法和属性是实例成员。
静态成员:构造函数的属性和方法是静态成员。
function Person(name, age) {// 实例成员this.name = namethis.age = age
}
const p = new Person('my', 18) // 实例对象
p.gender = '男' // 实例成员
Person.eyes = 2 // 静态成员
Person.sayHi = () => console.log('hi!') // 静态成员
Person.sayHi() // 调用
3、内置构造函数
js会把简单数据类型包装成复杂数据类型。
Object
常用三个静态方法:
const object = {name: "John",age: 30
}
// 1.Object.keys() 获得所有的属性名,返回数组
const arr1 = Object.keys(object)
console.log(arr1) // ["name", "age"]// 2.Object.values() 获得所有的属性值,返回数组
const arr2 = Object.values(object)
console.log(arr2) // ["John", 30]// 3.Object.assign() 深拷贝,修改新对象,不会影响原对象
const newObject = Object.assign({}, object)
//另一种写法
const newObject3 = {}
Object.assign(newObject3, object)
console.log(newObject3)
// 又一种:const newObject2 = { ...object }
Array
对于大部分实例方法,join,find,every,some,concat,sort,splice,reverse,findIndex等方法用的时候查就行。熟能生巧。
arr.reduce(function (上一次值, 当前值) { }, 起始值)
如果有起始值,就会把起始值作为上一次值,加进累加结果中。如果没有起始值,就把数组的第一个元素作为起始值,赋值给上一次的值使用。
const arr = [1, 2, 3, 4, 5];
// 1.forEach遍历数组
arr.forEach(function (item, index) {console.log(item, index);
});
// 2.map映射数组
const newArr = arr.map(function (item, index) {return item * 2;
});
console.log(newArr);
// 3.filter过滤数组
const newArr2 = arr.filter(function (item, index) {return item > 2;
});
console.log(newArr2);
// 4.reduce数组元素进行累加
const sum = arr.reduce(function (prev, item, index) {return prev + item;
}, 10);
// prev是上一次调用的返回值,item是当前元素,index是当前索引
console.log(sum);
静态方法:Array.from() 把伪数组转换为真数组。
const list = document.querySelectorAll('ul li')
console.log(list)
const liss = Array.from(list)
console.log(liss)
String
【】括住表示可选参数。
常见实例方法:length,split('分隔符'),substring(需要截取的第一个字符的索引【, 结束的索引号】),startsWith(检测的字符串【, 开始检测位置索引号】),includes(搜索的字符串【, 开始检测位置索引号】),toUpperCase,toLowerCase,indexOf,endWith,replace,match。
Number
二、原型
1、介绍
- 能够利用原型对象实现方法共享。
- 构造函数通过原型分配的函数是所有对象共享的。
- 每个构造函数都有一个 prototype 属性,指向另一个对象(这个对象被称为原型对象)。
- 这个对象可以挂载函数,对象实例化后不用多次创建原型函数,节约内存。
- 可以把内容一致的方法定义在原型对象上,让所有对象的实例共享这个方法。
- 构造函数和原型对象中的 this 都指向实例化对象。
function Perosn(name, age) {this.name = name;this.age = age;this.show = function () {console.log(this.name + " " + this.age);}// 原型属性Perosn.prototype.sing = function () {console.log('sing');}
}
const p1 = new Perosn("bibo", 21);
const p2 = new Perosn("niko", 18);
p1.show();
p2.sing();
p1.show === p2.show;//false
p1.sing === p2.sing;//true
例:给已有构造函数Array挂在原型对象,实现自定义功能。
const arr = [1, 2, 3];Array.prototype.sum = function () {return this.reduce((a, b) => a + b, 0);
};
console.log(arr.sum());Array.prototype.max = function () {// 用...运算符将数组展开// 用this获取数组,省的传入参数return Math.max(...this)
};
console.log(arr.max());
2、constructor
每个原型对象里都有constructor属性。该属性指向原型对象的构造函数。
console.log(Array.prototype.constructor===Array)//true
function Person(name, age) {this.name = name;this.age = age;this.show = function () {console.log(this.name + " " + this.age);}
}// 添加方法
Person.prototype.show1 = function () {console.log(this.name + " " + this.age);
}
console.log(Person.prototype);//{constructor: ƒ}// 批量添加方法
Person.prototype = {// 这样添加方法后constructor属性被覆盖没了,所以要添加constructor属性明确指向谁constructor: Person,sing: function () {console.log("I am singing");},dance: function () {console.log("I am dancing");},
}const p1 = new Person("Tom", 18);
p1.show();
p1.show1();
p1.sing();
p1.dance();
3、对象原型
对象有一个属性 __proto__ (__两个下划线)指向构造函数的 prototype 原型对象。所以实例对象能使用原型对象的方法。
[[ prototype ]]和 __proto__ 意义相同。
function Person() { }
const person = new Person();console.log(person.__proto__ === Person.prototype) // true
4、原型继承
构造函数通过原型继承父级属性和方法。
以下两个代码块有些问题:详见第二个的注释。
// 公共部分放在原型上
const A = { }// 构造函数 继承
function B() { }// B 通过原型继承 A
B.prototype = A
// 示例
const Person = {head: 1,eyes: 2,sayHi: function () {console.log('Hi');}
}//构造函数
function Man() {this.name = 'Man'this.age = 18;this.sayman = function () {//这样添加的方法,不会被其他继承Person的子类所调用console.log('I am a man');}
}
function Woman() {this.name = 'Woman'this.age = 18;
}// 继承
Man.prototype = Person;
Woman.prototype = Person;
// 上面这行代码覆盖了Person的constructor属性
// 下面添加了constructor属性,否则,man的constructor属性会指向Person
Man.prototype.constructor = Man;
Woman.prototype.constructor = Woman;const man = new Man();
console.log(man.head);// 1
console.log(man.sayHi()) // Hi
console.log(man.sayman()) // I am a manconst woman = new Woman();
Woman.prototype.saywoman = function () {// 这里添加的方法,会被其他继承Person的子类所调用console.log('I am a woman');
}
// 这是个问题
man.saywoman()
为了解决上面的问题——子类添加的方法不会被其他子类调用,保证子类之间的独立性——将父类作为构造函数书写,而不是一个对象。
function Person() {this.eyes = 2;this.head = 1;
}function Man() {}function Woman() {}// 继承
Man.prototype = new Person();
Man.prototype.constructor = Man;
Woman.prototype = new Person();
Woman.prototype.constructor = Woman;Woman.prototype.sayWoman = function () {console.log("I'm a woman");
}// 创建对象
const man = new Man();
const woman = new Woman();
woman.sayWoman();
//man.sayWoman(); 报错
总的来说,按第二种方法写代码,实现继承。
5、原型链

查找规则:
- 当访问一个对象的属性(包括方法)时,先查找这个对象自身有没有这个属性。
- 如果没有就查找他的原型。
- 还没有就找原型对象的原型,一直到Object(没有原型了,指向null)为止。
- __proto__对象原型的意义在于为对象的实例对象成员查找机制提供方向。
- 可以使用 instanceof 运算符检测构造函数的原型( prototype 属性)是否出现在某个原型链上。
function Person() {this.eyes = 2;this.head = 1;
}const person = new Person();
person instanceof Person;// true
person instanceof Object;// true
Person instanceof Object// true
person instanceof Array;// false
