从0开始学react netive:2.Javascript创建对象的方式_prototype原型的概念_原型继承

Javascript

1,概述

JavaScript一种直译式脚本语言,是一种动态类型、弱类型的语言。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML网页上使用,用来给HTML网页增加动态功能。
在1995年时,由Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为Netscape与Sun合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript。但实际上它的语法风格与Self及Scheme较为接近。
为了取得技术优势,微软推出了JScript,CEnvi推出ScriptEase,与JavaScript同样可在浏览器上运行。为了统一规格,因为JavaScript兼容于ECMA标准,因此也称为ECMAScript。
直译语言(Interpreted language),又称直译式语言,是一种编程语言,它不需要经过编译器先行编译为机器码,之后直接在CPU中执行,相反的,这种编程语言需要通过直译器,在执行期动态直译(interpreted)

2,JavaScript 数据类型

JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类型:
实例
var x // x 为 undefined
var x = 6; // x 为数字
var x = “Bill”; // x 为字符串

字符串
字符串是存储字符(比如 “Bill Gates”)的变量。
字符串可以是引号中的任意文本。您可以使用单引号或双引号:
实例
var carname=”Bill Gates”;
var carname=’Bill Gates’;

数字
JavaScript 只有一种数字类型。数字可以带小数点,也可以不带:
实例
var x1=34.00; //使用小数点来写
var x2=34; //不使用小数点来写

布尔
布尔(逻辑)只能有两个值:true 或 false。
var x=true
var y=false

数组
下面的代码创建名为 cars 的数组:
var cars=new Array();
cars[0]=”Audi”;
cars[1]=”BMW”;
cars [2] =”Volvo”;
或者 (condensed array):
vary cars=new Array(“Audi”,”BMW”,”Volvo”);
或者 (literal array):
实例
var cars=[“Audi”,”BMW”,”Volvo”];

对象
对象由花括号分隔。在括号内部,对象的属性以名称和值对的形式 (name : value) 来定义。属性由逗号分隔:
var person={firstname:”Bill”, lastname:”Gates”, id:5566};
对象属性有两种寻址方式:
实例
name=person.lastname;
name=person[“lastname”];

Undefined 和 Null
Undefined 这个值表示变量不含有值。
可以通过将变量的值设置为 null 来清空变量。

typeof
可以使用typeof操作符检测变量的数据类型
这里写图片描述

JavaScript中number、string、boolean、null和undefined型数据都是值类型,由于值类型数据占据的空间都是固定的,所以可以把它们存储在狭窄的内存栈。object、function和array等对象都是引用型数据

3,创建对象的方式

Object
var p = new Object();
p.name = “jack”;
p.age = 20;
p.sayName = function(){
alert(this.name);
}

1,字面量
var p = {name:”jack”,age:20,sayName:function(){alert(this.name);}};
2,工厂模式
function createPerson(name,age){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){
console.log(this.name);
}
return o;
}

var c = createPerson(“jason”,30);

3,构造函数
function Person(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
}
}

var p = new Person(“jack”,20);
alert(p instanceof Person);

构造函数的不同之处:
没有显示的创建对象
直接将属性和方法赋给了this对象
没有return语句
构造函数的问题:
每个函数都在每个实例上重新创建一遍,person1和person2都有一个名为sayName的函数,但是两个sayName函数是两个不同的Function实例

4,原型模式

function Person(){

}

Person.prototype.name = “jack”;
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert(this.name);
}

var p = new Person();
p.sayName();
理解原型对象prototype

我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
这里写图片描述

alert(Person.prototype.isPrototypeOf(p));
alert(Object.getPrototypeOf(p) == Person.prototype);

5,如何实现继承

Javascript实现继承主要依靠原型链

原型链

这里写图片描述

上面的代码中,我们没有使用SubType默认提供的原型,而是给它换了一个新原型,这个新原型就是SuperType的实例。于是,新原型不仅具有作为一个SuperType的实例所有拥有的全部属性和方法,而且其内部还有一个指针,指向了SuperType的原型。

原型链的问题
当原型包含引用类型的属性时,这些属性会被所有实例共享

function SuperType(){
this.colors = [“red”,”green”,”blue”];
}

function SubType(){
}
//继承了SuperType
SubType.prototype = new SuperType();

var instance1 = new SubType();
instance1.colors.push(“white”);
alert(instance1.colors);

var instance2 = new SubType();
alert(instance2.colors);

借用构造函数

在子类型构造函数内部调用父类型构造函数
call函数
语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
参数:thisObj 可选项。将被用作当前对象的对象。 arg1, arg2, , argN 可选项。将被传递方法参数序列。
说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

function SuperType(){
this.colors = [“red”,”green”,”blue”];
}

function SubType(){
//继承了SuperType
SuperType.call(this);
}

var instance1 = new SubType();
instance1.colors.push(“white”);

alert(instance1.colors);

var instance2 = new SubType();
alert(instance2.colors);

借用构造函数的问题:
方法都在构造函数中定义,函数复用是个问题,而且在父类原型中定义的函数,对于子类也是不可见的。

组合继承

function SuperType(name){
this.name = name;
this.colors = [“red”, “green”, “blue”];
}

SuperType.prototype.sayName = function(){
alert(this.name);
}

function SubType(name,age){
//继承属性
SuperType.call(this,name);
this.age = age;
}

//继承函数
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
}

var instance1 = new SubType(“Jack”,20);
instance1.colors.push(“white”);
alert(instance1.colors);
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType(“Rose”,22);
alert(instance2.colors);

6,闭包,

变量的作用域
根据作用域划分,变量有两种类型:全局变量和局部变量。
在函数内部访问全局变量:
var n=100;
function f1(){
alert(n);
}
f1(); // 100

函数外部自然无法读取函数内的局部变量
function f1(){
var n=100;
}
alert(n); // error

如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
function f1(){
var n=100;
function f2(){
alert(n); // 100
}
}

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗?
function f1(){
var n=100;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 100

闭包的概念
上面代码中的f2函数,就是闭包。
闭包,指有权访问另一个函数作用域中的变量的函数,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包的用途
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
        alert(n);
    }
    return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000

7,DOM编程

DOM就是HTML页面的模型,将每个标签都做为一个对象,JavaScript通过调用DOM中的属性、方法就可以对网页中的文本框、层等元素进行编程控制。比如通过操作文本框的DOM对象,就可以读取文本框中的值、设置文本框中的值。
HTML DOM定义了访问和操作HTML文档的标准方法。他把HTML文档呈现为带有元素、属性和文本的树结构。在层次图中,每个对象是它的父对象的属性,如Window对象是Document对象的父对象,所以在引用Document对象就可以使用Window.Document,相当于document是window对象的属性。对于每一个页面,浏览器都会自动创建Window对象、Document对象、Location对象、Navigator对象、History对象。
这里写图片描述

window.onload = function(){
    var child = document.createElement("span");
    child.innerHTML = "<i>jason</i>";
    var node = document.getElementById('wrapper');
    node.appendChild(child);
}

8,本节代码:

//对象的创建方式

//Object
var a = new Object();
a.name = "jack";
a.age = 20;
a.sayName = function(){
    console.log(this.name);
}

a.sayName();

//字面量
var b = {name:"rose",age:20,sayName:function(){
    console.log(this.name);
}};


b.sayName();

//工厂模式
function createPerson(name,age){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.sayName = function(){
        console.log(this.name);
    }
    return o;
}

var c = createPerson("jason",30);
c.sayName();

//构造函数
//更加符合OOP编程习惯
function Person(name,age){
    this.name = name;
    this.age = age;
    this.sayName = function () {
        console.log(this.name);
    }
}

var d1 = new Person("ricky",24);
d1.sayName();

var d2 = new Person("ricky",24);

//下面这样也是可以的 function 只实例化一次
/*
function sayName(){
    console.log(this.name);
}

function Person(name,age){
    this.name = name;
    this.age = age;
    this.sayName = sayName;
}

var d1 = new Person("ricky",24);
d1.sayName();

var d2 = new Person("rose",24);
d2.sayName();
*/

//原型
/*function Person(name,age){
    this.name = name;
    this.age = age;
}

Person.prototype.sayName = function(){
    console.log(this.name);
}

var d1 = new Person();
d1.sayName();*/

//父类型(js没有类的概念)
function SuperType(){
    this.flag = true;
}

SuperType.prototype.getXX = function(){
    return this.flag;
}

//子类型
function SubType(){
    this.subFlag = false;
}

//《JavaScript高级程序设计》

//继承的
//new SuperType()这个对象上有的所有属性和函数,SubType.prototype上都有了
//SubType.prototype有的,通过SubType构造函数实例化的对象,都会有
SubType.prototype = new SuperType();

//拷贝过程(可以这么理解)
//new SuperType() -> SubType.prototype -> s1

//检查是否继承了父类型的属性
var s1 = new SubType();
console.log(s1.getXX());
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值