JavaScript 与 ECMA-262

202 阅读6分钟

JS

  1. ECMA2005
  2. BOM
  3. DOM

复制变量值

  • 基础类型:会在新的变量上创建一个新值,存到新的变量列。两个变量互相不干扰、
  • 引用类型:

ES函数参数

  • es 函数传参的时候,并不在意参进来参数多少个。解析器不会去关注这个。 因为在函数内部,都是使用arguments这个类数组来取值的
    function add(){
      console.log(arguments.callee); // arguments.callee 为arguments所在的指针
    }

    var add2 = add; // 使用不带括号的函数名,访问的函数指针,跟复制引用类型值的一样的
  • es 参数是按值传递的,也就是复制一份到函数的内部。这样的话,基本类型跟引用类型就有区别了
   // 基本类型数据
   function addTen(num){
       num++;
        return num 
   }
   var count = 10
   alert(addTen(count)); // 11 
   // 相对于函数内部执行了一层 num = count; 基本类型数据这两种是互相不影响的
   alert(count); // 10
   
   // 引用类型
   function setName(obj){
     obj.name = 'neibu';
     obj = new Object();
     obj.name = 'new neibu'
   }
   var person = new Object();
   setName(person);
   
   
   // 使用不带括号的函数名,访问的函数指针,跟复制引用类型值的一样的,所以js函数没有重载
    function add(){

   }
   var add2 = add; 
   var a1 = function(){}
   a1 = function(){};
   // 后面一个a1 覆盖了前面一个a1的指针
   // 
   
   
   

函数内部属性

  • arguments 类数组参数指针
   function add(){
     console.log(arguments.callee); // arguments.callee 为arguments所在的指针
   }
  • this:引用的是函数据以执行的环境对象
   window.color = "red";
  var o = {color:'blue'};
  function sayColor(){
   console.log(this.color);
  }
  sayColor(); // red
  o.sayColor = sayColor;
  o.sayColor(); // blue
  // sayColor 是在全局定义的,引用this对象,调用函数之前,this的值不确定。因为this可能会在代码过程中引用不同的对象;
  // ps 函数名字只是一个包含指针的变量。只是个变量

函数属性与方法

属性
  • length 表示函数接收的参数个数
  • prototype
方法
  • call
  • apply

ES 作用域

  • 只能向上搜索,无法向下搜索变量

面向对象

创建对象
  • 对象就是一个一系列无序的属性的集合
  var obj = new Object()
  var obj = {}
  • 虽然Object构造函数和字面量可以创建对象,但是有个明显的缺点:会产生无序大量重复的代码,为了解决这个方法,使用工厂模式一种变体
  • 6.2.1 工厂模式
 function createPerson(name,age,jbo){
     /*
     * 工厂模式,内部创建个对象,往里面添加各种属性等。最后再返回
     */
     var o = new Object();
     o.name = name;
     o.age = age;
     o.sayName= function(){
      return this.name
     }
     return o;
 } 

 var ppp = createPerson();
  • 6.2.2 构造函数模式 ,使用new 来调用,内部会自动添加上下文环境
function Person(name){
    // var obj = new Object()  1 创建新对象(偷偷执行)
    // 类似 obj.call(this) 2 将构造函数的作用域赋值给新对象
    this.name = name;    // 执行构造之间的代码(3)
    this.sayName = function(){

    }
    // 偷偷执行return this
    // 4 返回新对象
}

var ppp1 = new Person('name');
  var ppp2 = new Person('name');
console.log(ppp1.sayName == ppp2.sayName);
  • new 做了什么: // 1 创建新对象 2 将构造函数的作用域赋值给新对象,因此this就指向这个对象 3 执行构造之间的代码()添加新属性 4 返回新对象

// 衍生知识点 // constructor // 对象的constructor属性最初是来标识对象类型的,对象检测还可以使用方法 instanceof

// 构造函数缺点 // 构造函数里面的方法要在每个函数里面重新创建遍,影响内存,因为创建两个完全一样任务的方法实例没有必要的,改造如下

 function PersonEdit(name){
    this.name = name;    // 执行构造之间的代码(3)
    this.sayName = say;
}
  function  say(){}
  • 6.2.3 原型模式
     // 函数中prototype是个指针,指向一个原型对象。 作用是所有的实例都能共享到原型对象上方法跟属性
     function Person(name){
      
   }
   console.log(Person.prototype,'6.2.3 原型模式')
   Person.prototype.name = '原型上的name'
   Person.prototype.sayName = function(){

   }
   var person1 = new Person();
   console.log(Object.getPrototypeOf(person1)===Person.prototype); // 判断某个实例的原型
  • prototype 原型对象 一创建函数,就会为该函数创建prototype 的原型对象,默认有个constructor的属性,这个属性指向 函数本身的指针 上面例子 Person.prototype.constructor = Person

  • 使用构造方式(new)调用函数,实例里有个 proto 指向原型对象,prototype; 实例对象就有原型对象上的方法跟属性

  • 获取某个对象属性 // 每当代码获取对象某个属性,先搜索实例本身搜索,实例找到则返回,没有则继续搜索指针指向的原型对象 即实例__proto__

  • 无法重写原型对象中的属性值,实例中如果定义了,则会先屏蔽下原型对象中的属性

使用delete删除实例属性,从而继续访问原型对象的属性

   person1.name = "实例上的属性"
   console.log(person1.name) // 实例上的属性
   delete  person1.name
    console.log(person1.name) // 原型上的name

    // in  for-in  或者  in  , 实例还是原型中的属性都能返回
    for(var key in person1){
      console.log(key)
    }

    // Object.keys 获取是实例上所有实例属性
     var person2 = new Person();
     person2.k = 3;
    console.log(Object.keys(person2))
  • 4 原型的动态性 由于原型中查找是一次搜索,所以对原型对象任何修改都能从实例中反映出来

    var friend = new Person();
    Person.prototype.sayFrind = function(){console.log('sayFrind')}
    friend.sayFrind(); // sayFriend
    // 首先创建 实例,在创建的时候调用sayFriend方法,又会找原型
    

    如果重新原型对象,就不同,如下

    function Test (){}; 
    var test = new Test(); // 先调用构造方法,此时test.__proto__ = Text.prototype; //等于它的原型对象,此时
    Test.prototype ={     // 此时又重新了原型对象的指针
      constructor:Test,
      name:'test-name',
      sayName:function(){
        console.log(this.name)
      }
    }

    console.log(test,'')   
    console.log(Object.isPrototypeOf(test) == Test.prototype)
    
    test.sayName() // 所以这里报错

// 缺点 引用类型的数据会指向同一个指针 传参

  • 6.2.4 组合使用构造函数与原型模式
    function Person(name){
      this.name = name;
   }
   Person.prototype.say = function(){}
  • 6.2.5 动态原型模式。组合型封装型不够
   function Person(name){
      this.name = name;
      if(typeof this.sayName!='function'){
         Person.prototype.sayName = function(){}
      }
   }
  • 6.2.6 寄生构造函数模式

继承

OO(面向对象都支持两种继承方式)

  1. 接口继承
    接口继承制继承方法签名,即只继承属性名称,里面的功能不管,
  2. 实现继承
    实现继承则把实际的方法功能。

js 无接口继承,只有方法继承,而且都是通过基本使用的原型链来的

  • 6.3.1 原型链继承
    (这里得知道ecma中原型对象的概念)函数的原型对象等于另外一个函数的实例,那这个函数的实例不就有另外一个函数所有属性跟方法了么。例子
   function SuperType(){
    this.property = '父类属性';
   }
   SuperType.prototype.getSuperValue = function(){
     return this.property
   }

   function SubType(){
    this.subproperty = '子类属性'
   }

   // 继承了父类SuperType
   SubType.prototype = new SuperType();  // 没有使用subType提供的默认原型,而是重写了原型对象,这也是实现本质

   var instance = new SubType();
   console.log(instance,'instance')
  • 确定原型与实例的关系
  1. instanceof 原理:用instanceof
console.log(instance instanceof SubType); //   true
console.log(instance instanceof SuperType);//  true
console.log(instance instanceof Object); //   ture

由于 instance 是 SubType、SuperType、Object 中任何一种类型的实例,所以都返回 true

  1. isPrototyoeOf()
Object.prototype.isPrototypeOf(instance);// true
SuperType.prototype.isPrototypeOf(instance);// true
SubType.prototype.isPrototypeOf(instance);// true