js笔记4-object 对象——原型,bug(精度不准)、call/apply、继承、instanceof、this、callee/caller

对象

对象的创建方法

  1. var obj = {} ----plainObject 对象字面量/对象直接量

  2. 构造函数

  • 系统自带的构造函数 new Object() /Array() /Number()
  var obj = new Object();
  • 自定义
  function Student(name){
      this.name = name;
      this.grade = 2016;
      this.read = function(){...}
  }
  var  studentHo = new Student('HoYuu');

构造函数内部原理

  1. 在函数体最前面隐式加上this = {}
  2. 执行 this.xxx = xxx;
  3. 隐式地返回this

包装类

String()
Number()
Boolean()

原型 prototype

prototype -----是祖先,值是一个对象
自身就有,初始为空对象,可手动添加属性
构造函数上的一个属性

eg.

  Student.prototype.school = 'tust';
  function Student(name){
      this.name = name;
      this.grade = 2016;
      this.read = function(){...}
  }
  var  studentHo = new Student('HoYuu');
  studentHo.school;

constructor

构造函数,原型中自带的属性之一

原型 proto

对象身上的
自带属性之一,也是原型(prototype是标准的,__proto__是非标准的——浏览器自己部署的)

eg.

Student 中

this = {
    __proto__:Student.prototype
}

Student.prototype 中

  __proto__:object
  • 对象找构造函数:obj.constructor
  • 对象找原型:obj.prototype
    浏览器添加了一条属性,代表构造函数上的原型:__ proto __
    __ proto __ === constructor.prototype
    对象.__ proto__ === 其构造函数.constructor.prototype

原型链

Object.creat(原型)

绝大多数对象的最终都会继承自Object.prototype
例外:Object.creat(null);

bug

JS 精度略微不准:
可正常计算的范围:小数点前16位,后16位

输出随机数

    for(var i = 0; i < 10; i++){
        // toFix(n) , 保留n位小数
        // 向上取整ceil , 向下取整floor
        var num = Math.floor(Math.random()*100);
        console.log(num);
    }

call/apply

作用:改变this指向
区别:后面传的参数形式不同

    function Person(name,age){
        this.name = name;
        this.age = age;
    } 
    var obj = {}
    Person.call(obj,'小明',20);
    // this ----> obj
    obj.name;// 小明
    obj.age;// 20
    function Person(name,sex,age)
    {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    function Student(name,sex,age,tel,grade){
        Person.call(this,name,sex,age);
     // Person.apply(this,[name,sex,age]);
        this.tel = tel;
        this.grade = grade;
    }
    var student = new Student('大富','男',18,13536,2018);

继承发展史

  1. 传统形式 ------原型链
    缺点:继承了过多没用的属性

  2. 借用构造函数 -------call/apply
    不能继承借用构造函数的原型
    每次构造函数都要多走一个函数

  3. 共享原型

  Son.prototype = Father.prototype;

不能随便改动自己的原型
Son往原型上添加信息,Father的原型也会有同样改变

  1. 圣杯模式
  function F(){}
    F.prototype = Father.protoytpe;
 
  Son.prototype = new F();

封装成函数

  function inherit(Target,Origin){
    function F(){};
    F.prototype = Origin.prototype;
    Target.prototype = new F();
    Target.prototype.constuctor = Target;
    Target.prototype.uber = Origin.prototype;//可不写,知道真正继承自谁
  }

  inherit(Son,Father);
  var son = new Son();

更好的写法:

  var inherit = (function (){
    function F(){};
    return function(Target,Origin){
      F.prototype = Origin.prototype;
      Target.prototype = new F();
      Target.prototype.constuctor = Target;
      Target.prototype.uber = Origin.prototype;
    }
  }());

命名空间

管理变量,防止污染全局,适用于模块化开发

更简洁:使用闭包-----立即执行函数,返回函数

属性的表示方法

  1. object.prop
  2. object[‘prop’]

对象的枚举

for in
会把原型的属性也打印出来

  var obj = {
    name : 'zfx',
    age : 18,
    grade : 'perfect',
    face : 100
  }
  // 打印出对象的属性
  for(var prop in obj){
    console.log(prop); 
    // 或者 console.log(obj[prop]);
    // 不能写成: obj.prop
  }
  1. !!! hasOwnProperty
    判断属性是否是自身拥有而不是原型的
  if(obj.hasOwnProperty()){
    console.log(obj[prop]);
  }
  1. in

  2. !!! instanceof

A instanceof B

实际:看A对象的原型链上,是否有B的原型

有一个变量,可能是 数组 或 对象,判断是哪种
var arr = [] || {};

  1. arr.constructor();
    数组返回 Array()
    对象返回 Object()

  2. arr instanceof Array
    数组返回 true
    对象返回 false

  3. Object.propeotype.toString.call(arr);
    数组返回 [Object Array]
    对象返回 [Object Object]

this

  1. 函数预编译过程 this ----》window
  2. 全局作用域里 this ----》window
  3. call/apply 可以改变函数运行时this指向
  4. obj.func(); func()里的 this 指向 obj
  var name = '222';
  var a = {
    name : '111',
    say : function (){
      console.log(this.name);
    }
  }
  var fun = a.say;
  fun(); //222
  a.say(); //111

  var b = {
    name : '333',
    say : function (fun){
      fun();
    }
  }
  b.say(a.say); //222
  b.say = a.say;
  b.say(); //333

arguments

  1. arguments.callee() 函数自身的引用
// 计算n的阶乘
  var num = (function(n){
    if(n == 1){
      return 1;
    }else return n * arguments.callee(n-1); 
  }(10))
  1. func.caller 函数是在哪被调用的
  function demo(){
    test();
  }
  function test(){
    console.log(test.caller);
  }
  demo();
  // 控制台结果:demo...

克隆

  var obj = {
    name : 'loly',
    height : 80,
    card : ['hello','vivi']
  }
  var obj1 = {};
  function clone (Origin, Target){
    Target = Target || {};//当没有传第二个参数时,自创Target为空对象
    for(var prop in Origin){
      Target[prop] = Origin[prop];
    }
  }
  clone(boj, obj1);
// obj1 其他属性值改变, obj 对应的不会改变;
// 但obj1 改变 card(数组)的值, obj 对应的也会改变

深度克隆

要求 obj1 无论改变什么值,都不会影响 obj

        function deepClone(origin, target) {
            target = target || {};
            var prop,
                arrStr = Object.prototype.toString,
                toStr = '[object Array]';
            for (prop in origin) {
                if (origin.hasOwnProperty(prop)) {
                    // 只克隆对象自身拥有的属性,而不克隆其原型链上的
                    if (prop !== null && typeof (origin[prop]) == 'object') {
                        //当属性值不为null 且 属性值为引用值
                        if (arrStr.call(prop) == 'toStr') {
                            //当引用值为数组
                            target[prop] = [];
                        } else {
                            // 当引用值为对象
                            target[prop] = {};
                        }
                        // 递归
                        deepClone(origin[prop], target[prop]);
                    } else {
                        //当属性值为原始值
                        target[prop] = origin[prop];
                    }
                }
            }
            return target;
        }
        deepClone(obj, obj1);

三目运算符

?:

条件判断? 是 :否 且返回值

   var num = 1 > 0 ? 6+5 : 1-5;

不可配置属性

有var的属性,是不可配置属性,不能delete

  var num = 1223;
  delete window.num; ----false

你可能感兴趣的:(js笔记4-object 对象——原型,bug(精度不准)、call/apply、继承、instanceof、this、callee/caller)