ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JavaScript高级

2019-09-03 22:02:25  阅读:186  来源: 互联网

标签:console log 对象 age JavaScript 高级 uname 构造函数


1.面向过程与面向对象

 1.1面向过程   面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。   面向过程是 实现代码逻辑的 步骤,主要是把重心点放在实现功能上,不太去考虑封装   优点: 效率高,但是维护起来太麻烦     1.2面向对象   面向对象是把事务分解成一个个对象,然后由对象之间分工合作。   主要的重心点,先放在功能模块的划分,然后想着什么功能模块可以去进行复用(可以进行抽取)   优点: 会让我们功能具备模块化开发,一个模块就负责一个功能,后续方便我们的维护   三大特性:继承性、封装性、多态性(抽象性)  

2.对象与类

  2.1 对象    对象是由属性和方法组成的:是一个无序键值对的集合,指的是一个具体的事物   属性:事物的特征,在对象中用属性来表示(常用名词)   方法:事物的行为,在对象中用方法来表示(常用动词)   创建对象的两种方法     1.字面量创建对象           var ldh = {       name: '刘德华',       age: 18       }       console.log(ldh);         2.构造函数创建对象       function Star(uname,age){
        this.uname = name;         this.age = age;       }       var ldh = new Star('刘德华',18); //实例化对象       console.log(ldh);  2.2 类    在 ES6 中新增加了类的概念,可以使用 class 关键字声明一个类,之后以这个类来实   例化对象。类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个,   通过类实例化一个具体的对象       2.2.1创建类      语法:          //步骤1 使用class关键字     class name {     // class body     }     //步骤2使用定义的类创建实例 注意new关键字     var xx = new name();   2.2.2类创建添加属性和方法       // 1. 创建类 class 创建一个类     class Star {       // 类的共有属性放到 constructor 里面 constructor是 构造器或者构造函数       constructor(uname, age) {       this.uname = uname;       this.age = age;       }//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐>注意,方法与方法之间不需要添加逗号       sing(song) {       console.log(this.uname + '唱' + song);       }     }   // 2. 利用类创建对象 new 实例化   var ldh = new Star('刘德华', 18);   console.log(ldh);   // Star {uname: "刘德华", age: 18}   ldh.sing('冰雨');     // 刘德华唱冰雨     注意点:     1. 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写     2. 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象     3. constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数     4. 多个函数方法之间不需要添加逗号分隔     5. 生成实例 new 不能省略     6. 语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function    2.2.3 类的继承   语法 :   class Father { }; // 父类       class Son extends Father { } // 子类继承父类 extends   示例 :          class Father {         constructor(surname) {         this.surname= surname;         }         say() {           console.log('你的姓是' + this.surname);         }       }       class Son extends Father{     // 这样子类就继承了父类的属性和方法       }       var damao= new Son('刘');       damao.say(); // 输出结果是   你的姓是刘      子类使用super关键字访问父类的方法         //定义了父类     class Father {       constructor(x, y) {       this.x = x;       this.y = y;       }       sum() {         console.log(this.x + this.y);       }     }     //子元素继承父类     class Son extends Father {       constructor(x, y) {         super(x, y); //使用super调用了父类中的构造函数       }     }     var son = new Son(1, 2);     son.sum();     //结果为3     注意:     1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的     2. 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)     3. 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,super 必须在子类this之前调用    2.2.4 时刻注意this的指向问题     我们在类中,去使用属性或者是调用方法千万不要忘记了用 this,     需要去关注的就是this的指向问题:         默认情况下,类中的this都指向的是当前实例化的对象,         除非 绑定事件之后this指向的就是触发事件的事件源  

3.构造函数和原型

  3.1 静态成员和实例成员

    实例成员 :实例成员就是构造函数内部通过this添加的成员,实例成员只能通过实例化的对象来访问

     以下代码里的 uname  age sing就是实例成员

function Star(uname, age) {
     this.uname = uname; 
     this.age = age; 
     this.sing = function() { 
            console.log('我会唱歌'); 
      } 
}
var ldh = new Star('刘德华', 18); 
console.log(ldh.uname);    //实例成员只能通过实例化的对象来访问    

 

     静态成员 :在构造函数本身上添加的成员 静态成员只能通过构造函数来访问    在ES5中只要被static修饰的属性和方法都是静态成员

     下列代码中 sex 就是静态成员

   

function Star(uname, age) { 
         this.uname = uname; 
         this.age = age; 
         this.sing = function() { 
               console.log('我会唱歌'); 
         } 
}
Star.sex = '男'; 
var ldh = new Star('刘德华', 18);
 console.log(Star.sex);          //静态成员只能通过构造函数来访问

  3.2构造函数的问题

    存在浪费内存的问题

    

function Star(uname , age) {
      this.uname = uname;
      this.age = age;        
      this.sing = function(){
             console.log('我会唱歌')
      }
}
var ldh = new Star("刘德华",18);
var shuji= new Star("书记",22);
ldh.sing();
shuji.sing();

   以上代码在调用sing方法时都会在内存开辟一个新的空间,如果有多个对象来调用sing方法就会占用过多内存,所以我们就用到了构造函数的原型 prototype。

  3.3 构造函数原型prototype

    构造函数通过原型分配的函数是所有对象所共享的。

     JavaScript 规定,每一个构造函数都有一个prototype 属性,指向另一个对象。注意这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。

     我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

     构造函数.prototype就可以获取原型对象

function Star(uname, age) { 
         this.uname = uname; 
         this.age = age;
 }
Star.prototype.sing = function() {
         console.log('我会唱歌'); 
}
var ldh = new Star('刘德华', 18); 
var zxy = new Star('张学友', 19); 
ldh.sing();  //我会唱歌 
zxy.sing();  //我会唱歌

 

   3.4 对象原型

    实例化对象都会有一个__proto__属性指向构造函数的原型对象,而我们的实例化对象可以使用对象原型的属性和方法就是因为有__proto__属性的存在

    实例化对象.__proto__ ===  构造函数.prototype

    它们的三角关系如下图:

      

    __proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype

   3.5 constructor构造函数

     对象原型( __proto__)和构造函数(prototype)原型对象里面都有一个属性constructor 属性

     constructor 我们称为构造函数,因为它指回构造函数本身。

     constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

    

    如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数 function Star(uname, age) {   this.uname = uname;   this.age = age; } // 很多情况下,我们需要手动的利用constructor 这个属性指回 原来的构造函数 Star.prototype = { // 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数   constructor: Star, // 手动设置指回原来的构造函数   sing: function() {     console.log('我会唱歌');   },   movie: function() {     console.log('我会演电影');   } } var zxy = new Star('张学友', 19); console.log(zxy)

   3.6 原型链和查找机制

    每一个实例对象又有一个proto属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有proto属性,这样一层一层往上找就形成了原型链。

    

  

     查找机制:

      当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性,如果自身有,就有自身的属性和方法。

      如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。

      如果还没有就查找原型对象的原型(Object的原型对象)。依此类推一直找到 Object 为止(null)。

      如果找到尽头(null)都没找到,是属性则返回undefined,是方法则报错

   

  3.7 原型对象中this的指向

    构造函数中的this和原型对象的this,都指向我们new出来的实例对象

   3.8 通过原型对象为数组扩展内置方法

    

var arr = [3,6,9,8,5]
arr.prototype.sum = function() { 
        var sum = 0; 
        for (var i = 0; i < this.length; i++) {
                  sum += this[i]; 
        }
        return sum; 
};              //此时数组对象中已经存在sum()方法了 可以用于数组.sum()进行数据的求和

  

4.继承

  4.1 call()

    call()可以调用函数   可以修改this的指向,使用call()的时候,()里的第一个参数是修改的this指向,参数2 参数3 使用逗号隔开

    

function fn(x, y) {
     console.log(this); 
     console.log(x + y); 
} 
var o = { 
    name: 'andy' 
};
fn.call(o, 1, 2); //调用了函数此时的this指向了对象o, 

    4.2 构造函数继承属性   

    1. 先定义一个父构造函数     2. 再定义一个子构造函数     3. 子构造函数继承父构造函数的属性(使用call方法)
// 1. 父构造函数 
function Father(uname, age) { 
// this 指向父构造函数的对象实例
      this.uname = uname; 
      this.age = age; 
}
// 2 .子构造函数 
function Son(uname, age, score) {
     // this 指向子构造函数的对象实例 
//3.使用call方式实现子继承父的属性 
      Father.call(this, uname, age);
      this.score = score; 
}
var son = new Son('刘德华', 18, 100); 
console.log(son);

   

   4.3 借用原型对象继承方法

    (1). 先定义一个父构造函数     (2). 再定义一个子构造函数     (3). 子构造函数继承父构造函数的属性(使用call方法)
// 1. 父构造函数 
function Father(uname, age) { 
// this 指向父构造函数的对象实例 
  this.uname = uname; 
  this.age = age; 
}
Father.prototype.money = function() { 
  console.log(100000); 
};
 //子构造函数   function Son(uname, age , score){      // this 指向子构造函数的对象实例     Father.call(this, uname, age);     this.score = score;   };
// Son.prototype = Father.prototype; 这样直接赋值会有问题,如果修改了子原型对 象,父原型对象也会跟着一起变化 
Son.prototype = new Father(); 
// 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数 
Son.prototype.constructor = Son; 
// 这个是子构造函数专门的方法 
Son.prototype.exam = function() { 
  console.log('孩子要考试'); 
}
var son = new Son('刘德华', 18, 100); 
console.log(son);

  

 5.ES5新增方法

  5.1 forEach()遍历数组  没有返回值

    array.forEach(function(value , index , array){....})

    value是每个数组元素

    index是每个元素索引值

    array是当前数组

  5.2 filter()筛选数组  其实也会遍历数组

    array.filter(function(value , index , array){

      return  条件表达式

    })

    返回的是一个新数组  括号跟的参数都是一样的

  5.3 some()   查找数组中是否有满足条件的元素  其实也会遍历数组

    array.some(function(value , index , array){

      return  条件表达式

    })

     返回值是布尔值,只要查找到第一个满足条件的元素就会终止循环 效率高  

 

   5.4 trim方法去除字符串两端的空格

    字符串的特性 不可变性

var str = ' hello ' ;
console.log(str.trim())  //hello 去除两端空格 
var str1 = ' he l l o ' ;
console.log(str1.trim())  //he l l o 去除两端空格

  5.5 获取对象的属性名 

    Object.keys(对象) 获取到当前对象中的属性名 ,返回值是一个数组

var obj = { 
    id: 1, 
    pname: '小米', 
    price: 1999,
    num: 2000 
};
var result = Object.keys(obj);
console.log(result)   //返回的新数组[id,pname,price,num]

  5.6 Object.defineProperty设置或修改对象中的属性

Object.defineProperty(对象,修改或新增的属性名,{ 
  value:修改或新增的属性的值, 
  writable:true/false,  //如果值为false 不允许修改这个属性值 
  enumerable: false,    //enumerable 如果值为false 则不允许遍历 
  configurable: false   //configurable 如果为false 则不允许删除这个属性 属性是否可以被删除或是否可以再次修改特性 
})

 

 

 

 

标签:console,log,对象,age,JavaScript,高级,uname,构造函数
来源: https://www.cnblogs.com/wsuyi/p/11443551.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有