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(); // Jake
person2.sayName(); // Jake
console.log(person1 instanceof Object); // true
console.log(person1 instanceof Person); // true
console.log(person2 instanceof Object); // true
console.log(person2 instanceof Person); // true
constructor as function
// use as a constructor
let person = new Person("Nicholas", 29, "Software Engineer");
person.sayName(); // "Nicholas"
// call as a function,不指定this,则为window
Person("Greg", 27, "Doctor"); // adds to window
window.sayName(); // "Greg"
// call in the scope of another object
let 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.prototype
Person.prototype.__proto__.constructor === Object
Person.prototype.__proto__.__proto__ === null
isPrototypeOf()
Person.prototype.isPrototypeOf(person1) // true
Person.prototype.isPrototypeOf(person2) // true
Object.create()
以某个对象为prototype创建对象
let biped = {
numLegs: 2
};
let person = Object.create(biped);
person.name = 'Matt';
console.log(person.name); // Matt
console.log(person.numLegs); // 2
console.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")); // true
delete 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
// sayHi
for (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__仍指向原prototype
friend.sayName(); // error
修改原生构造函数的prototype
String.prototype.startsWith = function (text) {
return this.indexOf(text) === 0;
};
let msg = "Hello world!";
console.log(msg.startsWith("Hello")); // true
原型的缺点:某个实例如果修改prototype里的属性或方法,实例之间会相互影响