【JS全解】JS对象分类

80 阅读3分钟

构造函数

  • 构造函数:可以构造出对象的函数。
  • 构造函数负责给对象添加本身独有属性
  • 构造函数的prototype对象负责保存对象的共有属性
  • 代码规范
    • 函数一般以动词、小写开头,例:createSquare()createElement()
    • 构造函数,会以名词、大写字母开头,例:new Square()new Cat()
    • 构造出来的对象,会以小写开头。
  • 用Object()也是构造函数,但是它构造出来的对象是最没有特点的。

利用函数和原型构造对象

  • 利用原型链的机制,来构造多个有共同特征的对象,可以避免代码的重复、占用内存过多。
    let squareList = []
    let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5]
    
    function createSquare(width) {
    	let obj = Object.create(createSquare.squarePrototype)
    	obj.width
    	return obj
    }
    
    createSquare.squarePrototype = {
    	getArea() {
    		return this.width * this.width
    	},
    	getLength() {
    		return this.width*4
    	},
    	constructor: createSquare
    }
    
    for(let i = 0; i < widthList.length; i++) {
    	squareList[i] = createSquare(widthList[i])
    }
    
    console.log(squareList[0].getArea === squareList[1].getArea)
    
  • 将上述代码用new优化,来简化成下面的代码:
    let squareList = []
    let widthList = [5, 6, 5, 6, 5, 6, 5, 6, 5]
    
    function Square(width) {
    	// let obj = Object.create(createSquare.squarePrototype)
    	this.width = width // obj.width
    	// return obj
    }
    
    Square.prototype.getArea = function(){
    	return this.width * this.width
    }
    Square.prototype.getLength = function() {
    	return this.width*4
    }
    
    for(let i = 0; i < widthList.length; i++) {
    	squareList[i] = new Square(widthList[i])
    }
    
    console.log(squareList[0].getArea === squareList[1].getArea)
    
    • new在这段代码中,代替了let obj = Object.create(createSquare.squarePrototype)的作用。
  • new的作用
    • 自动创建空对象。
      • let obj = Object.create()
    • 自动创造并关联对象原型。
      • createSquare.squarePrototype
    • 自动将空对象作为this关键字运行构造函数。
      • obj.width
    • 自动return this
      • return obj
  • 注意
    • 在这种构造方法中,只有prototype.的属性才是共有属性。
    • 要先创建原型,才能调用构造函数,因此prototype.不能写在构造函数内容。

数组对象

  • 定义一个数组:
    var arr = [1, 2, 3]
    var arr  = new Array(1, 2, 3) // 元素为1、2、3
    var arr = new Array(3) // 长度为3
    
  • 数组对象的独有属性
    • index(索引)
    • length
  • 数组对象的共有属性
    • push():在数组末尾添加元素,并返回该数组的新长度。
    • pop():在数组末尾删除一个元素,并返回该元素的值。
    • shift():在数组开头添加元素,并返回该数组的新长度。
    • unshift():在数组开头删除一个元素,并返回该元素的值。
    • join():将一个数组的所有元素拼接成一个字符串,并返回这个字符串。
  • 数组对象相比Object对象,就多一层原型。
    let a = []
    a.__proto__.__proto__ === window.Object.prototype // true
    
  • 注意
    • 数组对象的index是字符串,不是数字。

函数对象

  • 定义一个函数:
    function fn(x, y){return x + y}
    var fn2 = function fn(x, y){return x + y}
    var fn = (x, y) => x + y
    var fn = new Function('x','y','return x+y')
    
  • 函数对象的独有属性
    • name
    • length:形参的数量。
  • 函数对象的共有属性
    • call
    • apply
    • bind

constructor属性

window是谁构造的?

  • 通过constructor属性可以查看对象的构造者:
    window.constructor // ƒ Window() { [native code] }
    
  • 因此,window和Window不是一回事。后者其实应该是Window()。

window.Object是谁构造的?

window.Object.constructor // ƒ Function() { [native code] }
  • 所有的函数都是Function()构造的。
  • Window()也是Function()构造的。

Function()是谁构造的?

Function().constructor // Function()
  • 浏览器构造了Function(),然后指定它的构造者为自己。

Object.prototype是谁构造的?

Object.prototype.constructor // ƒ Object() { [native code] }
  • 浏览器构造了Object.prototype,然后指定它的构造者为Object()。

class语法

  • ES 6中引入的新语法:
    class Square{
    	constructor(width){
    		this.width = width
    	}
    	getArea(){
    		return this.width * this.width
    	}
    }
    
  • 只能使用这种形式的函数构造,使用其他形式会报错。

class语法进入的概念

class Square{
  static x = 1
  width = 0
  constructor(width){
    this.width = width
  } 
  getArea(){ 
    return this.width * this.width 
  }
  getLength(){
    return this.width * 4
  }
  get area2(){
    return this.width * this.width
  }
}
  • static x = 1:设置一个只能通过Square.x调用的静态变量x(类似Java)。
  • width = 0:为width设定初始值(默认值)。
  • get area2() {}:设置只读属性。调用只读属性时不用加小括号。

class中两种函数写法的区别

  • 语法1:
    class Person{
        sayHi(name){}
        // 等价于
        sayHi: function(name){} 
        // 注意,一般我们不在这个语法里使用箭头函数
    }
    //等价于
    function Person(){}
    Person.prototype.sayHi = function(name){}
    
  • 语法2:
    class Person{
      sayHi = (name)=>{} // 注意,一般我们不在这个语法里使用普通函数,多用箭头函数
    }
    // 等价于
    function Person(){
        this.sayHi = (name)=>{}
    }
    
  • 注意
    • 冒号变成了等于号。

拓展

函数的prototype属性

  • 所有JS中的函数,一开始就自带一个prototype属性。

JS中怎么知道函数有几个参数?

  1. 看文档
  2. 看源代码

JS中变量所存储的内容

  • JS中变量只能存储简单数据类型或者地址。
  • 因此prototype属性中存储的是原型的地址。
  • Object() ≠ Object类型的原型
  • JS源代码中不存在这样一个变量名
    • 它的变量名为Object。
    • 它所指向的地址有且仅拥有Object数据类型对象的所有属性。
  • prototype属性不等于原型。

原型公式

  • 对象.__proto__ === 其构造函数.prototype
  • 任何对象都有以上规律。
  • Object.prototype是例外,因为它的值为null。

this和箭头函数

  • 如果要使用this,那么函数不能是箭头函数。

类型和类的区别

  • 类型:JS数据的分类,共有七种。
  • 类:针对与对象的分类,有无数种。