constructor
function Person() {this.name = "Jake";this.sayName = function() {console.log(this.name);};}// constructor是Person()let person1 = new Person();let person2 = new Person; // 如果不传参数可以省略括号person1.sayName(); // Jakeperson2.sayName(); // Jakeconsole.log(person1 instanceof Object); // trueconsole.log(person1 instanceof Person); // trueconsole.log(person2 instanceof Object); // trueconsole.log(person2 instanceof Person); // true
constructor as function
// use as a constructorlet person = new Person("Nicholas", 29, "Software Engineer");person.sayName(); // "Nicholas"// call as a function,不指定this,则为windowPerson("Greg", 27, "Doctor"); // adds to windowwindow.sayName(); // "Greg"// call in the scope of another objectlet o = new Object();Person.call(o, "Kristen", 25, "Nurse");o.sayName(); // "Kristen"
Prototype
为了减少重复的property和method, 每个函数都有一个prototype, prototype对象里存储了所有实例的共有属性和方法。每个函数的prototype里都有一个constructor属性,指向构造函数本身。Person.prototype.construtor === Person
每个实例的proto都指向构造函数的prototype
**
Person.prototype.__proto__ === Object.prototypePerson.prototype.__proto__.constructor === ObjectPerson.prototype.__proto__.__proto__ === null
isPrototypeOf()
Person.prototype.isPrototypeOf(person1) // truePerson.prototype.isPrototypeOf(person2) // true
Object.create()
以某个对象为prototype创建对象
let biped = {numLegs: 2};let person = Object.create(biped);person.name = 'Matt';console.log(person.name); // Mattconsole.log(person.numLegs); // 2console.log(Object.getPrototypeOf(person) === biped); // true
delete
delete用于删除属性
delete person1.name;
hasOwnProperty()
hasOwnProperty()只有当属性在实例上才返回true
function Person() {}Person.prototype.name = "Nicholas";let person1 = new Person();person1.name = "Greg";console.log(person1.hasOwnProperty("name")); // truedelete person1.name;console.log(person1.hasOwnProperty("name")); // false
in 操作符
in操作符,所有能被访问的属性(方法),不管是在实例里还是prototype里,都返回true
let obj = {name:'h', age:20, sayHi(){console.log('hi')}}obj.__proto__.color = 'red''sayHi' in obj // true'color' in obj // true'constructor' in obj // true
for-in
for-in返回所有能被访问且能枚举的属性(方法)
for (item in obj) console.log(item)// name// age// sayHi// color
Object.keys()
接受一个对象参数,返回对象实例里的能被枚举的属性(方法)数组
for (item of Object.keys(obj)) console.log(item)// name// age// sayHifor (item of Object.keys(obj.__proto__)) console.log(item)// color
Object.getOwnPropertyNames()
接受一个对象参数,返回对象实例里的所有属性(方法)数组
for (item of Object.getOwnPropertyNames(obj.__proto__)) console.log(item)// constructor// __defineGetter__// __defineSetter__// hasOwnProperty// __lookupGetter__// __lookupSetter__// isPrototypeOf// propertyIsEnumerable// toString// valueOf// __proto__// toLocaleString// color
Object.getOwnPropertySymbols()
symbol没有名字
let k1 = Symbol('k1'),k2 = Symbol('k2');let o = {[k1]: 'k1',[k2]: 'k2'};console.log(Object.getOwnPropertySymbols(o));// [Symbol(k1), Symbol(k2)]
in, for-in, Object.keys()都没有顺序,Object.getOwnPropertyNames(), Object.getOwnPropertySymbols(), and Object.assign()按Number升序,接着string and symbol keys按插入顺序
Iteration遍历
Object.values(), Object.entries()
const o = {foo: 'bar',baz: 1,qux: {}};console.log(Object.values(o));// ["bar", 1, {}]console.log(Object.entries((o)));// [["foo", "bar"], ["baz", 1], ["qux", {}]]
prototype和proto存的是地址
function Person() {}let friend = new Person();Person.prototype = {constructor: Person,name: "Nicholas",age: 29,job: "Software Engineer",sayName() {console.log(this.name);}};// 中途修改prototype,旧实例的__proto__仍指向原prototypefriend.sayName(); // error
修改原生构造函数的prototype
String.prototype.startsWith = function (text) {return this.indexOf(text) === 0;};let msg = "Hello world!";console.log(msg.startsWith("Hello")); // true
原型的缺点:某个实例如果修改prototype里的属性或方法,实例之间会相互影响
