constructor

  1. function Person() {
  2. this.name = "Jake";
  3. this.sayName = function() {
  4. console.log(this.name);
  5. };
  6. }
  7. // constructor是Person()
  8. let person1 = new Person();
  9. let person2 = new Person; // 如果不传参数可以省略括号
  10. person1.sayName(); // Jake
  11. person2.sayName(); // Jake
  12. console.log(person1 instanceof Object); // true
  13. console.log(person1 instanceof Person); // true
  14. console.log(person2 instanceof Object); // true
  15. console.log(person2 instanceof Person); // true

constructor as function

  1. // use as a constructor
  2. let person = new Person("Nicholas", 29, "Software Engineer");
  3. person.sayName(); // "Nicholas"
  4. // call as a function,不指定this,则为window
  5. Person("Greg", 27, "Doctor"); // adds to window
  6. window.sayName(); // "Greg"
  7. // call in the scope of another object
  8. let o = new Object();
  9. Person.call(o, "Kristen", 25, "Nurse");
  10. o.sayName(); // "Kristen"

Prototype

为了减少重复的property和method, 每个函数都有一个prototype, prototype对象里存储了所有实例的共有属性和方法。每个函数的prototype里都有一个constructor属性,指向构造函数本身。
Person.prototype.construtor === Person

每个实例的proto都指向构造函数的prototype
**

  1. Person.prototype.__proto__ === Object.prototype
  2. Person.prototype.__proto__.constructor === Object
  3. Person.prototype.__proto__.__proto__ === null

isPrototypeOf()

  1. Person.prototype.isPrototypeOf(person1) // true
  2. Person.prototype.isPrototypeOf(person2) // true

Object.create()

以某个对象为prototype创建对象

  1. let biped = {
  2. numLegs: 2
  3. };
  4. let person = Object.create(biped);
  5. person.name = 'Matt';
  6. console.log(person.name); // Matt
  7. console.log(person.numLegs); // 2
  8. console.log(Object.getPrototypeOf(person) === biped); // true

delete

delete用于删除属性

  1. delete person1.name;

hasOwnProperty()

hasOwnProperty()只有当属性在实例上才返回true

  1. function Person() {}
  2. Person.prototype.name = "Nicholas";
  3. let person1 = new Person();
  4. person1.name = "Greg";
  5. console.log(person1.hasOwnProperty("name")); // true
  6. delete person1.name;
  7. console.log(person1.hasOwnProperty("name")); // false

in 操作符

in操作符,所有能被访问的属性(方法),不管是在实例里还是prototype里,都返回true

  1. let obj = {name:'h', age:20, sayHi(){console.log('hi')}}
  2. obj.__proto__.color = 'red'
  3. 'sayHi' in obj // true
  4. 'color' in obj // true
  5. 'constructor' in obj // true

for-in

for-in返回所有能被访问且能枚举的属性(方法)

  1. for (item in obj) console.log(item)
  2. // name
  3. // age
  4. // sayHi
  5. // color

Object.keys()

接受一个对象参数,返回对象实例里的能被枚举的属性(方法)数组

  1. for (item of Object.keys(obj)) console.log(item)
  2. // name
  3. // age
  4. // sayHi
  5. for (item of Object.keys(obj.__proto__)) console.log(item)
  6. // color

Object.getOwnPropertyNames()

接受一个对象参数,返回对象实例里的所有属性(方法)数组

  1. for (item of Object.getOwnPropertyNames(obj.__proto__)) console.log(item)
  2. // constructor
  3. // __defineGetter__
  4. // __defineSetter__
  5. // hasOwnProperty
  6. // __lookupGetter__
  7. // __lookupSetter__
  8. // isPrototypeOf
  9. // propertyIsEnumerable
  10. // toString
  11. // valueOf
  12. // __proto__
  13. // toLocaleString
  14. // color

Object.getOwnPropertySymbols()

symbol没有名字

  1. let k1 = Symbol('k1'),
  2. k2 = Symbol('k2');
  3. let o = {
  4. [k1]: 'k1',
  5. [k2]: 'k2'
  6. };
  7. console.log(Object.getOwnPropertySymbols(o));
  8. // [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()

  1. const o = {
  2. foo: 'bar',
  3. baz: 1,
  4. qux: {}
  5. };
  6. console.log(Object.values(o));
  7. // ["bar", 1, {}]
  8. console.log(Object.entries((o)));
  9. // [["foo", "bar"], ["baz", 1], ["qux", {}]]

都是浅拷贝;
symbol属性值会被忽略;

prototype和proto存的是地址

  1. function Person() {}
  2. let friend = new Person();
  3. Person.prototype = {
  4. constructor: Person,
  5. name: "Nicholas",
  6. age: 29,
  7. job: "Software Engineer",
  8. sayName() {
  9. console.log(this.name);
  10. }
  11. };
  12. // 中途修改prototype,旧实例的__proto__仍指向原prototype
  13. friend.sayName(); // error

修改原生构造函数的prototype

  1. String.prototype.startsWith = function (text) {
  2. return this.indexOf(text) === 0;
  3. };
  4. let msg = "Hello world!";
  5. console.log(msg.startsWith("Hello")); // true

原型的缺点:某个实例如果修改prototype里的属性或方法,实例之间会相互影响